Full writeup including mitigations, threat hunting and other detection ideas.👇
(7/7)
haxrob.net/hiding-in-pl...
@haxrob.net.bsky.social
Telco / mobile and IoT security. Surfing the information super highway one keystroke at a time. https://haxrob.net
Full writeup including mitigations, threat hunting and other detection ideas.👇
(7/7)
haxrob.net/hiding-in-pl...
This method can be utilized to perform process masquerading..
Here an implant appears to be running from /usr/sbin/auditd but it's actually 'fileless'.
No '(deleted)', no ':memfd', no '/dev/shm', no ptrace, no LD_PRELOAD. Just stealth.
(6/7)
Malware can use the unshare() or clone() syscalls to create the new mount and user namespaces. The uid/grp mapping is done by writing to procfs followed by mount().
If the process enters a spin lock, it can be used to keep a persistent hold of the 'stash space'
(5/7)
Create a new mount and user namespace, mapping the unprivileged uid to uid 0.
Here the root user logs in [4] and can't see the file created by the unprivileged user in the /root directory
(4/7)
As a bonus, commands in this shell will not be written to the history file as we mounted over the user's home directory.
No need to set HISTFILE=/dev/null.
Once the shell exits, artifacts evaporate. Nothing touches the disk.
Now how to do this as an unprivileged user? (3/7)
Let's start with the most simple example. Select a mount namespace that is not used by systemd/init.
Migrate the current shell into that process's mount namespace and mount a tmpfs file system.
Anything that writes the mounted path is concealed from users on the host. (2/7)
A relatively unknown but particularly stealthy technique to hide files on Linux hosts. On unhardened boxes, unprivileged users can conceal files from even the root user. Disk content remains in memory, hindering disk acquisition during forensic investigation. (1/7) 👇
13.07.2025 07:39 — 👍 6 🔁 1 💬 2 📌 0Full writeup:
haxrob.net/bpfdoor-past...
(21/21)
There is a particular byte sequence used here that might have some meaning. The hex encoded bytes can be copied from the blog entry linked below if others would like to have a go at this piece of the puzzle.
(20/21)
Another interesting feature is the ability to configure the masqueraded process name and implant password. Rather then depend on an external config file, it modifies itself.
(19/21)
Unlike the familiar BPFDoor, it has a persistence mechanism built in - specify 'x' as an argument and it modifies the system wide bash profile for all users
(18/21)
BPFDoor would write a file to /var/run as a mutex lock (to prevent multiple instances. NotBPFDoor uses a semaphore by calling semget. The semaphore key is an epoch timestamp - Friday, June 5, 2015. Interesting
(17/21)
It's 'NotBPFDoor' because it does not use BPF filters. When looking for magic packets, the user space process receives all TCP traffic. An early revision of BPFDoor?
(16/21)
So what does this really tell us? Perhaps BPFDoor in some form or another has been around for quite some time and may give proximity to a particular intrusion set.
Next we have what I'll call "NotBPF" with the first submitter from HK in 2016. Let's look into it.
(15/21)
The sniffdoor notes reveal future ambitions that made it's way into BPFDoor (img from writeup: haxrob.net/bpfdoor-past...)
(14/21)
We also see overlapping code with the WNPS rootkit
(13/21)
sniffdoor was advertised in hacking forums in 2007
(12/21)
How about the BPF "client / controller"? Also overlapping code / strings with sniffdoor
(11/21)
Sniffdoor and BPFDoor have quite some overlapping code.
(10/21)
The "Just for Fun" ASCII program author also had a blog with the same title. On the archived blog are links to source code to various software they had written. The "adore-ng" rootkit should be familiar to some. But what is "sniffdoor"?
(9/21)
... justforfun is the password found in the leaked BPFDoor source code. It's also the password used in samples found in the wild.
"Just For Fun" is the name of a biography by Linux Torvalds. Just a coincidence?
(8/21)
A few weeks after that date, a simple program was published where a tank fires shells across the terminal. A program "Just For Fun". Why does the phrase sound familiar ?
(7/21)
Since we are taking a closer look at #BPFDoor, let's do a bit of digging. Remember this hard coded epoch timestamp used for tampering it's file modified time- October 30, 2008 ?
(6/21)
So while it looks the process has a socket open for UDP only, the malware can still receive the same TCP, UDP and ICMP magic wakeup packets - making if functionally equivalent to how it behaves when raw sockets was used.
(5/21)
Super tricky!
And this explains this change: The first byte is expected to be the first byte of a IP packet. In the leaked BPFDoor source, we see it considers the size of an ethernet header (14 bytes).
02.06.2025 14:27 — 👍 0 🔁 0 💬 1 📌 0$ man socket.7 gives some clues. It hints with AF_PACKET, the protocol may have priority over the socket type. So ETH_P_IP overrides SOCK_DGRAM. Also, the layer 2 (ethernet) frame will be removed.
(3/21)
Perhaps it's only looking for UDP magic packets? Not so fast. Let's look at what changed.
BPF filter is used as before, but the socket is opened with type SOCK_DGRAM, but the protocol is ETH_P_IP.
What's the defined behaviour here?
(2/21)
Newer variants of the #BPFDoor has an interesting modification made that avoids detections looking for processes with raw sockets. The kernel reports SOCK_DGRAM rather then rather loud "SOCK_RAW". Here we have a sample found in the recent SK telco breach.
(1/21)
That was a fun episode 🌶️ 🌶️
27.12.2024 11:01 — 👍 0 🔁 0 💬 0 📌 0Nice work, very promising project 👍
25.11.2024 00:29 — 👍 0 🔁 0 💬 0 📌 0