BPFDoor Malware Evolves – Stealthy Sniffing Backdoor Ups Its Game
What is BPFdoor?
BPFdoor is a Linux-specific, low-profile, passive backdoor intended to maintain a persistent, long-term foothold in already-breached networks and environments and functions primarily to ensure an attacker can re-enter an infected system over an extended period of time, post-compromise.
The malware gets its name from its usage of a Berkley Packet Filter – a fairly unique way of receiving its instructions and evading detection, which bypasses firewall restrictions on incoming traffic.
The malware is associated with a Chinese threat actor, Red Menshen (AKA Red Dev 18), which has been observed targeting telecommunications providers across the Middle East and Asia, as well as entities in the government, education, and logistics sectors since 2021.
When it was first discovered, approximately one year ago, BPFdoor was noted for its effective and elegant design and its high emphasis on stealth – an essential element in maintaining undetected long-term persistence.
Recently, Deep Instinct’s threat lab observed and analyzed a previously undocumented and fully undetected new variant of BPFdoor.
New, Stealthier Variant
Several key differences that make this new variant even stealthier compared to the previous version include the following:
|“New stealthy” 2023 variant
|“Old” 2022 variant
Static library encryption
Bind shell and iptables
No hardcoded commands – all commands are sent through the reverse-shell
One of the most significant differences compared to the previous variant lies in the removal of many of its hardcoded indicators, making the newer version more difficult to detect. Since first seen on VirusTotal in February 2023, the new variant remained undetected and is still undetected as of this writing.
BPFdoor Technical Analysis
When executed, the BPFdoor sample will attempt to create and get a lock on a runtime file at “/var/run/initd.lock” and will exit if it fails using that file as a makeshift mutex.
If successful, BPFdoor will fork itself and continue to run as a child process and in this context will close its stdin, stdout, and stderr streams, and set itself to ignore the following operating system signals:
SIGHUP ("signal hang-up") is a signal sent to a process when its controlling terminal session is closed.
SIGINT (“signal interrupt”) is a signal sent when a user interrupts a program (Ctrl + C)
SIGQUIT is a signal sent to terminate a process.
SIGPIPE is a signal sent when a pipe breaks.
SIGCHLD is a signal sent when a child process exits.
SIGTTIN is a signal sent to a process attempting to read from the same terminal session and is blocked.
SIGTTOU is a signal sent to a process attempting to write to the same terminal session and is blocked.
Ignoring these signals hardens BPFdoor against tampering with its processes.
Having set up the above, BPFdoor then allocates a memory buffer and creates a socket as follows:
It will proceed to specify the following socket options using setsockopt:
And will read from it in a loop (further described below) using recvfrom:
An interesting point in the above-described flow is that the “addr” parameter is zeroed out in the call to recvfrom; it should point to a specific address from which to read data. The socket is not connected and no bind or listen calls have been made. So, what exactly is going on here?
Interpreting the exact arguments that are used to create the socket reveals that the call is structured as follows:
This creates the socket as a special packet sniffing socket which is able to read every packet that is sent to the machine from the ethernet layer and above without being bound to any specific protocol.
BPFdoor employs this type of packet sniffing socket to read data with recvfrom, even without an “addr” parameter, by using the loop below to search for a specific “magic” byte sequence:
“Magic” byte sequence: \x44\x30\xCD\x9F\x5E\x14\x27\x66
Once found, the loop will break and BPFdoor will continue to Its next phase of operation.
But, that creates quite a lot of traffic that BPFdoor will need to go through.
Let’s examine the usage of setsockopt a bit further. When parsing its arguments, we arrive at the following code:
This is where BPFdoor gets its name from. The above code that attaches a Berkley Packet Filter to the socket; this is the very same mechanism that underpins infosec staples such as libpcap and allows BPFdoor to filter out “uninteresting” types of data coming through its socket.
A Berkley Packet Filter can be defined as in the example below, which allows TCP over IPv4:
By setting the socket option SO_ATTACH_FILTER and pointing filter to the following sock_filter_code:
BPFdoor guides the kernel to set up its socket to only read UDP, TCP, and SCTP traffic coming through ports 22 (ssh), 80 (http), and 443 (https).
Because of its positioning at such a low level, BPFdoor does not abide by any firewall rules, and can bypass any firewall restrictions on incoming traffic and listen for packets that otherwise wouldn't have surfaced to the machine's user mode.
When BPFdoor finds a packet containing its “magic” bytes in the filtered traffic it will treat it as a message from its operator and will parse out two fields and will again fork itself.
The parent process will continue and monitor the filtered traffic coming through the socket while the child will treat the previously parsed fields as a Command & Control IP-Port combination and will attempt to contact it.
An interesting point to note, this variant of BPFdoor contains a pre-compiled version of libtomcrypt, an open-source encryption library, as can be seen in the sample’s contained strings, which also offer a few additional insights:
We can see that the library was compiled at the beginning of October 2022 using GCC on a system running Red Hat Linux. This may suggest that this variant has been operational significantly earlier than its first appearance on VirusTotal.
By compiling our own version of the library in similar fashion and using bindiff to compare against BPFdoor we can see its statically linked exports:
Having made the comparison, we determined that BPFdoor is using libtomcrypt functionality to set up a secure and encrypted “reverse-shell” session with its Command & Control. This replaced its previous mechanism.
After this session is established, BPFdoor will begin a loop that can be described by the following:
BPFdoor retains its reputation as an extremely stealthy and difficult-to-detect malware with this latest iteration.
Regardless of whether one considers the encryption library compilation time (October 2022) or its initial submission to VirusTotal (February 2023) as indicative of when this sample was first put into use, it is truly amazing how long it has remained fully undetected.
afa8a32ec29a31f152ba20a30eb483520fe50f2dce6c9aa9135d88f7c9c511d7 – BPFDoor ELF SHA256
/var/run/initd.lock – BPFDoor "mutex”
Command and Control
T1205 - Traffic Signaling
Attacker employs “magic” values to trigger response.
“Magic” byte sequence
Command and Control
T1205.002 - Traffic Signaling: Socket Filters
Attacker attaches filter to a network socket.
Usage of Berkley Packet Filter
Command and Control
T1573 - Encrypted Channel
Attacker employs encrypted Command & Control communication.
Usage of libtomcrypt
T1106 – Native API
Attacker calls upon native OS APIs in order to execute behaviors.
Usage of popen
Earlier variant analysis:
Deep Instinct takes a prevention-first approach to stopping ransomware and other malware using the world’s first and only purpose-built, deep learning cybersecurity framework. We prevent ransomware, zero-day threats, and previously unknown malware in <20 milliseconds, 750x faster than the fastest ransomware can encrypt. Deep Instinct has >99% zero-day accuracy and promises a <0.1% false positive rate. The Deep Instinct Prevention Platform is an essential addition to every security stack – providing complete, multi-layered protection against threats across hybrid environments.