← Reports

InfoStealer

VIPKeyLogger - ENCRYPTED.ps1

Author
Moise Medici
Updated
09 May 2026 · Completed
Difficulty
Easy
Platform
Windows
Family
VIPKeyLogger
Languages
PowerShellVB.NET
MITRE
T1059.001 (Command and Scripting Interpreter: PowerShell) T1027 (Obfuscated Files or Information) T1027.007 (Obfuscated Files or Information: Dynamic API Resolution) T1027.009 (Obfuscated Files or Information: Embedded Payloads) T1027.010 (Obfuscated Files or Information: Command Obfuscation) T1027.013 (Obfuscated Files or Information: Encrypted/Encoded File) T1055.012 (Process Injection: Process Hollowing) T1070.004 (Indicator Removal: File Deletion) T1140 (Deobfuscate/Decode Files or Information) T1497.001 (Virtualization/Sandbox Evasion: System Checks) T1620 (Reflective Code Loading) T1539 (Steal Web Session Cookie) T1552.001 (Unsecured Credentials: Credentials In Files) T1552.002 (Unsecured Credentials: Credentials in Registry) T1555.003 (Credentials from Password Stores: Credentials from Web Browsers) T1016 (System Network Configuration Discovery) T1033 (System Owner/User Discovery) T1082 (System Information Discovery) T1217 (Browser Information Discovery) T1614 (System Location Discovery) T1005 (Data from Local System) T1048.003 (Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 Protocol) T1567 (Exfiltration Over Web Service)

Question 3: What is the content of decodedAssemblyBytes?

To get the value of the decodedAssemblyBytes, the same technique as before can be used: a breakpoint after the initialization of the variable, executing the code and saving the variable to file:

Terminal window
$decodedAssemblyBytes | Out-File .\Desktop\stage3.txt

To be safer, the Invoke-ManagedAssembly execution can be commented out to avoid unwanted execution. Taking a look at the file, the first few lines are:

77
90
144
0
3
0

When in doubt of the content of a file, CyberChef can be useful to automatically identify it. In fact, typing 77 90 in the Input area of CyberChef shows a wand-like icon on the bottom of the page, like the screenshot below:

CyberChef offering its magic wand next to the Output pane once 77 90 is typed into the Input.
Fig. 2: CyberChef offering its magic wand next to the Output pane once 77 90 is typed into the Input.

This will autopopulate the Recipe section with “From Decimal”:

The wand fills the recipe with From Decimal, which turns 77 90 into MZ.
Fig. 3: The wand fills the recipe with From Decimal, which turns 77 90 into MZ.

As shown from the output section, 77 90 is translated to MZ, the two bytes indicating a Windows executable. Keeping the same Recipe, the whole content of the file can be pasted into CyberChef and downloaded. This allows us to have the actual executable file. At this point stage3.txt has been renamed as stage3.exe.

Before looking at the content of this new executable, it is useful to see how it gets executed. In Invoke-ManagedAssembly the first argument, RawAssemblyBytes, is the one filled with decodedAssemblyBytes. Within the function it is used as follows:

stage2.ps1
$loadedAssembly = [System.Reflection.Assembly]::Load($RawAssemblyBytes)
# Get the specified type from the loaded assembly
$targetType = $loadedAssembly.GetType($TargetTypeName)
# Configure binding flags for static public methods
$bindingAttributes = [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static

This is a common .NET malware technique where a .NET code is loaded and executed directly from memory via reflection, similar to process injection in that malicious code runs inside a legitimate process without a normal executable launch. The powershell function [System.Reflection.Assembly]::Load is taken directly from .NET netstandard.dll.

Also, note that the Invoke-ManagedAssembly function has other arguments:

stage2.ps1
$executionResult = Invoke-ManagedAssembly -RawAssemblyBytes $decodedAssemblyBytes `
-TargetTypeName 'MAFFIA.ProcessHollowing' `
-TargetMethodName 'Execute' `
-MethodArguments $invocationParameters

TargetTypeName is probably the name of an object or class defined in the code, since it is used in the GetType 5 method, which returns the type of that object, specifically from the Microsoft documentation:

An object that represents the specified class, or null if the class is not found.

TargetMethodName is then retrieved from the class object:

stage2.ps1
$targetMethod = $targetType.GetMethod($TargetMethodName, $bindingAttributes)

And invoked with the MethodArguments arguments:

stage2.ps1
return $targetMethod.Invoke($null, $MethodArguments)

The arguments are the .NET framework path, and the content of ExecutionPayload.

stage2.ps1
$invocationParameters = [object[]]@($frameworkToolPath, $ExecutionPayload)

We can then safely assume that decodedAssemblyBytes contains a .NET executable, which will be confirmed shortly. We have however the clear objective of having to understand what MAFFIA.ProcessHollowing is.