{
	"id": "ac61b22e-71d0-4c32-8949-07d0ccfc6d3f",
	"created_at": "2026-04-06T00:09:23.396382Z",
	"updated_at": "2026-04-10T03:22:01.288363Z",
	"deleted_at": null,
	"sha1_hash": "96b1cb3997bc26b6ed2dfeaad356519068455c1f",
	"title": "Endgame Harvesting: Inside ACRStealer’s Modern Infrastructure",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 975661,
	"plain_text": "Endgame Harvesting: Inside ACRStealer’s Modern Infrastructure\r\nBy G DATA Security Center\r\nPublished: 2026-03-12 · Archived: 2026-04-05 23:03:19 UTC\r\n03/12/2026\r\nReading time: 9 min (2319 words)\r\nThe vector is deceptive. The Loader is sophisticated and at this point, it’s already game over.\r\nWritten by John Dador\r\nFrom our previous article of HijackLoader, the observed payload is a rebranded ACRStealer initially reported\r\nby Proofpoint in the early half of last year. This updated variant follows similar evasion techniques and C2\r\ninitialization strategy to make it even stealthier. Since ACRStealer is known as a Malware as a Service (MaaS), it\r\nmakes sense that it is now being used as one of the many payloads used by HijackLoader. This signifies\r\nthat ACRStealer is not just a repurpose malware, but a continuously refined and rebranded module actively\r\ndeployed through intricate loaders. This\r\nintegration with HijackLoader highlights ACRStealer’s versality and modularity, which will likely attract more\r\nmalicious actors to use it as a final payload. \r\nFor this part, we will highlight ACRStealer’s evasion techniques, C2 communication and notably\r\nits stealing capabilities, where our focus on the latter provides new insights. \r\nNTCalls and WoW64 SysCalls\r\nInterestingly, this version of ACRStealer uses dynamic API resolution through NTDLL and\r\nWoW64 syscalls, as initially reported by Proofpoint. Most malware families typically rely on higher-level Win32\r\nAPIs to directly perform evasion or execution, which are easily detected and monitored by security products such\r\nas EDRs. By using low-level syscalls, this ACRStealer variant can bypass user-mode hooks and reduce\r\nits detectability. \r\nThe new variant ‘s behavior starts by accessing the Process Environment Block (PEB) to locate the ntdll.dll. It\r\nthen manually parses the Export Address Table (EAT) to resolve the function names which are done via a\r\nmodified version of djb2 also used in HijackLoader but with a different seed. After lookup, it saves the\r\ncorresponding address and System Service Number (SSN) of the function and stores it to a global variable.\r\nLastly, in order to execute the system call, it makes use of the Wow64 transition gate, bypassing the Win32 API\r\nlayer and user-mode hooks.   \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 1 of 13\n\nFigure 1: Dynamic API Resolution\r\nAFD and NTSockets\r\nEarly versions of ACRStealer leveraged the use of Dead Drop Resolver (DDR) to obfuscate C2\r\ncommunication. This version however uses NTSockets and Ancillary Function Driver (AFD) to establish a C2\r\nconnection without using the Winsock or any high-level APIs.  \r\nThe code starts by manually constructing the string \\\\Device\\\\Afd\\\\Endpoint\\\\, which represents the AFD’s native\r\npath object. Then it builds an OBJECT_ATTRIBUTE structure along with a UNICODE_STRING structure.\r\nTogether, these structures describe the target object to the Windows Object Manager. With this setup, the\r\ncode invokes NtCreateFile allowing it to resolve and open the AFD Endpoint from user mode and instead of going\r\nthrough the Win32 API layer, again evading detection.  \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 2 of 13\n\nFigure 2: Building AFD Endpoint with Object_Attribute Struct\r\nNext, the function constructs deliberately crafted strings. The first resulting string\r\nis AfdOpenPacketXX.  Alongside this crafted string, it also defines protocol-related values (2, 1, 6) which\r\ncorresponds to AF_INET, SOCKSTREAM and IPPROTO_TCP indicating that it is preparing a TCP IPv4 socket\r\nwithout importing ws2_32.socket. It then dynamically builds another string NTCreateFile, by concatenating string\r\nvalues. The function passes this string to the custom function resolver mentioned earlier and uses the Wow64\r\ntransition gate to invoke the native system call directly.  \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 3 of 13\n\nFigure 3: Building AFDOpenPacketXX with TCP Ipv4 socket\r\nLayered Communication\r\nAnother key aspect of this version is how it implemented a layered communication design: it first establishes a\r\nraw TCP connection, then performs SSL/TLS over that connection through SSPI. \r\nAfter preparing the AFD endpoint handle, it manually parses the target IP address in this case\r\nis 157[.]180[.]40[.]106 and converts it to a network byte order together with port 443. It then configures the\r\nremote C2 endpoint via native AFD IOCTLS using NtDeviceIoControlFile which is an equivalent of connect() in\r\nWinSock. This suggests that it wants to blend in with the normal HTTPS traffic while using AFD. At this stage, it\r\nalready established a plain TCP connection. During analysis, the IP address 157[.]180[.]40[.]106 was no longer\r\nresponsive and might already be down thus it immediately terminates the endpoint. \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 4 of 13\n\nHowever, if the IP address was still up, the sample would start to do a TLS Handshake over the established TCP\r\nconnection. This TLS handshake happens with the use of SSPI through AcquireCredentialsHandleA which\r\nuses Microsoft Unified Security Protocol Provider and is followed by a call to InitializeSecurityContextA with a\r\nhardcoded pszTargetName in playtogga[.]com. This is looped in a statement where it checks a\r\ncode 0x90312 which translates to the SSPI status code\r\nof SEC_I_CONTINUE_NEEDED. That indicates that additional handshake tokens must be exchanged\r\nbefore TLS session is fully established. \r\nPost-Handshake Transmission: Plaintext vs TLS\r\nOnce the handshake is completed, the code exits and frees the temporary buffers. It prepares the HTTP request\r\nbefore evaluating the transmission mode. One of eight HTTP methods (GET, HEAD, POST, PUT, DELETE,\r\nCONNECT, OPTIONS, TRACE, PATCH) is used in this function where the POST method is the default. The\r\nresulting header is exactly as follows “POST / HTTP/1.1\\r\\nHost: playtogga[.]com\\r\\nConnection:\r\nclose\\r\\nContent-Length: 48\\r\\nContent-Type: application/octet-stream\\r\\n\\r\\n”.  \r\nAfter building the HTTP request header, it checks a configuration flag to determine whether the data will be sent\r\nin a plaintext or TLS wrapped data. If the flag is configured as 0, it will send the constructed HTTP request over\r\nthe established TCP connection via AFD. It's like a single shot HTTP request commonly used for beaconing.\r\nOtherwise, it will start to encrypt the HTTP request header using the EncryptMessage API before sending.  Based\r\non the status code (200), it either decrypts the data from the server using AES-256 with a hardcoded 32-byte key\r\nor executes a Sleep command for two seconds before entering a recovery routine where it tries to initiate a re-connection.  \r\nLoot, Sleep and Repeat\r\nThis section reveals ACRStealer’s range of data stealing functions. Apart from the unique methods used to\r\nsteal sensitive browser information, the analysis also confirms that this variant deliberately\r\ntargets gamers shown through exfiltration of Steam account data, something that has not been encountered and\r\nstudied before.  \r\nThe stealing features of ACRStealer are all based on eight short string config keys each associated with\r\na type value (integer, array, bolean, string). These config keys are passed as an argument which will define what\r\ntask the code will execute. The function that we labeled as GetArrayField (Figure 4) returns the array values\r\nstored under a given config key which will be used later on by task handling functions starting\r\nfrom 0x4126D0 to determine which files and directories to target. \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 5 of 13\n\nFigure 4: The 8 short string config keys and the series of stealing functions\r\nThe very start of each stealing function is presented like this [Figure 5]. It checks if the config key value is indeed\r\nan array (type 4). It then iterates over each element of the array to confirm that each is an object (type 5) holding\r\ndictionary-like keys such as (p, tp, n, f, r). These dictionary keys are then used to retrieve the task’s parameters on\r\nwhat we assume to be name (n), target path (tp), argument (a), files (f) and recursive flag (r).  \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 6 of 13\n\nFigure 5: The config key checker and task parameter assignment observed at the start of most\r\nstealing functions.\r\nLeveraging the use of NT syscalls, ACRStealer starts with the USERPROFILE and recursively searches for\r\nsensitive files using NtOpenFile and NtQueryDirectoryFile which loops until there are no more entries.  Also,\r\nmost of the stealing functions immediately submit the stolen data to its C2 server and are then followed by a call\r\nto NtDelayExecution before going to the next stealing function. \r\nFigure 6: File traversal through the use of NT Syscalls\r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 7 of 13\n\nThe stealing functions below are executed as follows. \r\nIt first extracts the browser master encryption key by locating Local State file to retrieve the values\r\nof encrypted_key and decrypting it via Base64, stripping the DPAPI prefix and calling the\r\nAPI CryptUnprotectData which returns the raw AES master key. After obtaining the master key, it proceeds to\r\nenumerate user directories and browser profiles. This is a classic DPAPI abused to decrypt browser artifacts. The\r\nstolen data is then extracted into a txt file with the hardcoded name “d5e48e78-2951-4117-b806-\r\ne4f8e626f28c.txt“ before sending it to the C2 server. \r\nFigure 7: DPAPI abuse to acquire browser’s master key\r\nThe next stealing function performs a more advanced technique. It first enumerates browser profiles and extracts\r\nthe raw AES master keys for each profile. But then it employs an App Bound Encryption bypass which is done via\r\nshellcode process injection into the target browser. This makes it clear that ACRStealer also targets Chrome\r\nversions lower than v127 before app bound encryption was introduced. The goal of the latter was to prevent\r\nstealers from using DPAPI to decrypt sensitive data. The shellcode also plays an important role here since it has\r\nno import table, it only dynamically resolves and calls CopyFileA from kernel32.dll. I also noticed a string\r\n“Elevator.exe “which strongly suggests that it copies Elevator.exe or elevation_service.exe which performs\r\nprivilege operations for Chrome. Successful execution of this results in bypassing the App-Bound encryption and\r\neventually decrypting sensitive browser information. \r\nThe next sets of stealing functions are exfiltration of Login Data, Cookies and WebData. It also does full victim\r\nfingerprinting (Machine GUID, architecture, username, locale, build time etc.) where it again writes to the same\r\nhardcoded txt file before sending it to the C2 server. \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 8 of 13\n\nThe next stealing function exfiltrates Steam credential and tokens. It retrieves information via the install path\r\nregistry where it extracts the account/login token data from the configuration files (loginuser.vdf, local.vdf). It\r\nagain writes into the same hardcoded txt file before sending it to the C2 server. \r\nThe next function shows the stealer‘s capability to execute multiple secondary payloads based on the assigned\r\nfield configuration. In this function, the additional payloads(exe, cmd, dll and ps1) are placed into four cases.\r\nThis determines what type of execution the code will perform. There are three execution methods present:\r\ntwo Powershell commands via CreateProcessA and one process hollowing via rundll32.exe as a host process.  \r\nFigure 10: Switch case function for secondary payloads\r\nRather than invoking rundll32.exe through its legitimate DLL export interface (rundll32.exe \u003cdll\u003e, \u003cexport\u003e), the\r\nmalware employs process hollowing. It first spawns rundll32.exe in a suspended state using\r\nthe CREATE_SUSPENDED flag, injects the malicious payload, overwrites its\r\nprimary thread’s instruction pointer and resumes the thread to effectively bypass the process’s original entry\r\npoint. \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 9 of 13\n\nFigure 11: Process Hollowing function\r\nThe first PowerShell command function is responsible for executing only .ps1 and .exe files. The ps1 file is\r\nexecuted with the arguments “-NoProfile -ExecutionPolicy Bypass -File. For exe files, it simply prepares\r\nthe executable’s path as the command line. In both cases, the ps1 and exe file are executed via CreateProcessA.  \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 10 of 13\n\nFigure 12: The first PowerShell command\r\nFigure 13: The second PowerShell command\r\nThe second PowerShell command, aside from the bypass execution method, also use DownloadString which\r\nis executed via Invoke-Expression(IEX). This function only executes a type ‘4‘ which maps to a .ps1 file. \r\nThis version of ACRStealer might still be incomplete. We do not see a function that executes a .cmd file and the\r\nprocess hollowing is mapped to type ‘5‘ which does not properly correspond to the declared type ‘3‘ or .dll files.\r\nThis might also suggest a coding error or oversight as both cmd and dll files are declared but never executed.  \r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 11 of 13\n\nFigure 14: Supposedly function invoking CMD and DLL payloads\r\nThe last function involves recursively traversing files while skipping executable file types (exe, dll, msi, sys)\r\nlikely to avoid collecting system files. It captures screenshots by dynamically resolving libraries (user32.dll \u0026\r\ngdi32.dll) and APIs such as GetDC, CreateCompatibleBitmap, BitBlt via GetProcAddress. The captured\r\nimage is then stored as “g/screen/screen.bmp“.  Each stolen data is inserted into an in-memory ZIP archive where\r\nit is enforced to only have a maximum size of 40MB (0x2800000). Once complete, it will be sent to the C2 server\r\nover TCP port 443.  \r\nPatterns in Action\r\nACRStealer’s activity showed a very interesting operational pattern. VirusTotal telemetry indicates an active\r\ninfection in countries such as USA, Mongolia and Germany. All identified samples are communicating with\r\nthe same IP address (157[.]180[.]40[.]106) and five of\r\nthe seven samples collected also establish connections to playtogga[.]com. Playtogga is a popular fantasy soccer\r\nplatform currently headquartered at Austin, Texas. In contrast, PiviGames is the domain from\r\nwhich HijackLoader was downloaded, eventually dropping ACRStealer generally sees higher traffic in Spanish-speaking countries. This interaction suggests ACRStealer’s broad and diverse digital footprint possibly to\r\nmask and blend with legitimate traffic. \r\nWithin the first few days of this year 2026, the malicious URL (hxxps://pivigames[.]blog/adbuho) is still active\r\nbut there seems to be some changes. It still follows the same script and redirection chain, but it now leads to a new\r\ncloud storage and hosting service, in this case Mega. The downloaded zip file now only contains a single\r\nexecutable file with no resource file or folders unlike the previously downloaded zip file. Analysis showed that the\r\nexecutable file, which is also named “Setup.exe”, is a variant of LummaStealer.   \r\nThis only indicates that the threat actors in control of the PiviGames infrastructure are still continuously infecting\r\nsystems. Just like in this case, they might still actively approach unsuspecting users in popular gaming platforms\r\nlike Steam, Discord, Twitch, and even social media like Reddit to compromise and steal data.   \r\nIOCs\r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 12 of 13\n\n[1] FuII Verslon Setup 6419 σρєи Download.zip (sic!), archive with all\r\nfiles 418A1A6B08456C06F2F4CC9AD49EE7C63E642CCE1FA7984AD70FC214602B3B1 \r\n[2] ACRStealer, payload - 59202cb766c3034c308728c2e5770a0d074faa110ea981aa88f570eb402540d2 -\r\n Win32.Trojan-Stealer.ACRStealer.%M \r\n[3] LummaStealer -f88c6e267363bf88be69e91899a35d6f054ca030e96b5d7f86915aa723fb268b - Win32.Trojan-Stealer.LummaStealer.%M \r\n[4] 157[.]180[.]40[.]106 – ACRStealers’ C2 URL - Malware \r\n[5] playtogga[.]com – ACRStealers’ C2 URL - Malware \r\nRelated articles:\r\n Content\r\nNTCalls and WoW64 SysCalls\r\nAFD and NTSockets\r\nPatterns in Action\r\nIOCs\r\nPrevious Research on ACRStealer\r\nRelated articles\r\nSource: https://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nhttps://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure\r\nPage 13 of 13",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://blog.gdatasoftware.com/2026/03/38385-acr-stealer-infrastructure"
	],
	"report_names": [
		"38385-acr-stealer-infrastructure"
	],
	"threat_actors": [],
	"ts_created_at": 1775434163,
	"ts_updated_at": 1775791321,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/96b1cb3997bc26b6ed2dfeaad356519068455c1f.pdf",
		"text": "https://archive.orkl.eu/96b1cb3997bc26b6ed2dfeaad356519068455c1f.txt",
		"img": "https://archive.orkl.eu/96b1cb3997bc26b6ed2dfeaad356519068455c1f.jpg"
	}
}