BPFDoor - Part 1 - The past
An exploration the archeological roots of the BPFDoor Linux malware.

BPFDoor
malware. In Part 2 we look at evasive changes in samples reported in a significant telecommunication company's breach - along with IoCs.
In this post we follow breadcrumbs sprinkled across the Internet's past in an attempt to understand BPFDoor
potential code origin which span almost 20 years ago. We also uncover a fork or early version which appeared in the wild in 2016
Refer to the following timeline of events described:

This post attempts to mostly avoid what's already been covered in prior literature. For readers not familiar with BPFDoor
, the following resources are recommended for prior reading: Trend Micro (2025), Sandfly Security (2022), Elastic (2022).
Just for fun
Central to this post is sniffdoor
- the source code is not easy to find. A mirror can be found here.
Many early samples of BPFDoor
found in the wild use the hardcoded password justforfun
. We also see this in leaked source code:

Pivoting off this phrase, we land back to the year 2011, stumbling on an archived blog, "Just for fun", also sharing its title with the name of book by Linus Torvalds, published in 2001. The domain was registered in 2011:

BPFDoor
includes a hardcoded epoch timestamp used for time stomping. The date is October 30, 2008 GMT

21 days after this hardcoded date, a program titled "Program Just for Fun!" was published by the developer of sniffdoor
:

If you compile and run the program, you will be greeted with an ASCII animation of a tank firing shells across your terminal.

Also in 2006, the developer released source to soshell
(source mirror)

And sniffdoor
(cloud-sec.org archive.org, archive.org, archive.org):

Both sniffdoor
and BPFDoor
use the pty
control handling from another program, bindtty
(mirror). While bindtty
is not dated, there is some code overlap with a kernel rootkit, published in Phrack #58 in 2001 by sd@fs.cz
.
Timestamps from the obtained sniffdoor
archive align with the posting date on forum.eviloctal.com


The comment
section in the compiled binaries in the tarball indicate the binary compiled on the Asianux distribution giving a compilation date sometime after January 23rd 2006:

As such, we can date sniffdoor
to be likely developed and released between 2006-2007.
Similarities between BPFDoor
and sniffdoor
(v1.0):
- Sharing the same code for its pseudo terminal handling (taken from
bindtty
). - Numerous overlapping function names/routines
- Uses raw sockets to intercept magic / wakeup packets
- Supports both connect/bind and reverse shells
BPFDoor
has improved stealth capability and other improvements that's not present in sniffdoor
:
- Uses a
BPF
filter to reduce volume of traffic hitting the process as it looks for magic packets - In addition to
TCP
for magic packets,UDP
andICMP
is also supported - Payload is encrypted
- Anti-forensics such as masquerading its process name, time-stomping, overwriting environment variables
- Injects
iptables
rules inbind
mode
As an example with BPFDoor
on the left and sniffdoor
on the right. Both routines originate their code from bindtty.c
:

BPFDoor
's decompiled controller's getshell
function overlaps with sniffdoor
's getshell_local
. Note that there is no known source for the controller in the public domain at the time of writing.

As sniffdoor
and soshell
borrowed code from bindtty.c
. The soshell
client source includes a comment that code was also taken from conntty
which could not be found archived or otherwise.
In the todo file of snniffDoor
's code we can see features that would make it's way into BPFDoor
:
In future (I hope):
- Support ICMP,UDP protocol woke up.
- Make it more stable.
Also found are comments on an intention to add process name masquerading - in a dynamic manner - another feature which also made its way into BPFDoor

An (automated) translation:
Hide, hide, now the initial plan is to use a fake process name to fool around, making it look like -bash, hehe, then create an LKM to hide it, ideally achieving dynamic hiding.
We see thatBPFDoor
did 'fake' it's process name from by randomly selecting from a predefined list. (The newest versions removed the random selection, as seen in part 2 of this post)
An LKM
would also too eventuate as the WNPS
rootkit - also sharing code overlaps with both sniffdoor
and the bpfdoor
client:


The circumstantial details here provides no evidence in respect to the attribution of the author of BPFDoor
. The choice of the password justforfun
for BPFDoor
is an curious one though. Some possible explanations:
- The
sniffdoor
developer,WZT
was the very first initial developer ofBPFDoor
- Another developer visited
WZT
's blogs, obtained thesniffdoor
orsoshell
code and was influenced with the phrasing "Just for fun" or added the term as password as a means of a false flag (misattribution) - The phrasing is a complete coincidence, the developers of
BPFDoor
andWZT
being Linux enthusiasts, both enjoyed reading Linus's book, titled "Just For Fun". - Also must be considered is the possibility that
BPFDoor
andsniffdoor
both borrowed code from a common source other thenbindtty.c
. This code goes back many decades and version/derivates are likely to have been shared amongst individuals and groups.
The sniffdoor
developer released other (more well known) software in that era, such as the adore-ng
rootkit (which was reported to be included in APT 41's toolset (Mandiant report, page 47).
sniffdoor
developer was coincides around the time they were reported to have left the NCPH Group (source, page 203). Notably, some remaining members of NCPH Group became associated to APT 41. Also for interesting reading is this testimony by Adam Kozy.
NotBPFDoor - An early direct descendent
While testing YARA
rule sets for BPFDoor
for part 2 of this post, a very early version of BPFDoor
was identified. The two samples are not compatible with the observed clients to date: and more notably, does not use a BPF
filter (as sniffdoor
). Hence, to differentiate, we give the name - NotBPFDoor
.
Two samples were uploaded in August 2016, with the initial submitters originating from Hong Kong (link). This was before the source code had leaked into the public domain.


NotBPFDoor
shares significant code overlap with BPFDoor
. Although there is extra functionality which has been removed in BPFDoor
samples:
- Optional boot persistence mechanism
- Ability to re-configure it's process name and password through a configuration menu
Additionally, NotBPFDoor
:
- Uses a single password rather then two (to differentiate mode of operation)
- Uses a semaphore as a mutex lock rather then writing a file to disk
Initial process name and passwords
A single hardcoded process name is used (portmap
and rhnsd
). Later BPFDoor
samples randomly select from a list of process names. The malware then goes full circle as we will see with the most recent variants revert back to a single process name.

Mutex Lock
- The mutex lock uses libc's
semget
function to set a semaphore for the process rather then to write a file to disk. The semaphore key is1433490800
(0x55715570)
which corresponds to a epoch date of Friday, June 5, 2015 UTC. This could hit at the approximate year the code was in development.

If the process abnormally terminates, the semaphore is still held by the kernel, meaning it will have to be manually removed before the process can be started again (unless the system is rebooted)
$ ipcs
...
------ Semaphore Arrays --------
key semid owner perms nsems
0x55715570 0 root 600 1
$ ipcrm -S 0x55715570
Persistence
A feature that seems to be removed in later BPFDoor
samples is the ability for maintaining persistence across system reboot. If the x
flag is used, the file /etc/profile.d/lang.sh
is checked to contain the string unset LC_TIME
. It then adds itself to this script which will be run every time a user logs in with a shell.

Self Modifying Configuration
The masqueraded process name and password can be configured with the C
switch. A "start time" and "end time" can also be configured.

The start/end time options appear to be unused.
Rather then write to an external configuration file, the changed parameters appended to itself, increasing the ELF
binary file size by 598 bytes. The first 64 bytes is a fixed byte sequence originating from a global in the .ro
section. If these 64 bytes are not found at the end of itself, then they will be written - followed by 534 bytes of the actual configuration:

The 'marker' bytes Shannon entropy: 5.65625
. It's origin has not been identified.
In one version it looks as if hex encoded bytes were pasted into the source as a string, rather then as as actual byte values (a likely mistake, fixed in the second identified sample)

If others would like to have a go at trying to identify what the byte sequence could be, here it is:
4A 8A BA AB A8 80 F7 F0 24 C6 A5 4B 4A B4 0D DD E4 C6 FF 80 75 0E B7 25 7C 95 B2 9A E6 6C A6 87 B2 CC 06 FF 26 D2 3D FF 26 7E 37 1B 10 D3 1B 51 AC 7B 81 60 08 F8 50 EC 05 90 68 4B FF 44 14 8B
An early packet_loop
We see a very early version of the packet_loop
routine. Only TCP
is supported and no setsockopt
with SO_ATACH_FILTER
. The hardcoded magic bytes are 0x5571
.
(BPFDoor
samples have been observed to use 0x7255
, 0x5293
and 0x39393939
).

In summary, NotBPFDoor
appears to either an early fork or early version of BPFDoor
with slightly different functionality.
Next, onto part 2 where we jump to the year 2025 and look at how the malware has evolved.
Appendix
Citations
A list of links referenced in this post series (This is the only content in which an LLM was used to assist in writing this post)
- Malpedia details on BPFDoor
- TechCrunch timeline of SKT data breach
- Boho (KrCERT) samples page
- Trend Micro BPFDoor research (2025)
- Sandfly Security BPFDoor analysis (2022)
- Elastic security labs on BPFDoor (2022)
- Sniffdoor Mirror
- Bindtty Mirror
- Archived cloud-sec blog
- Just for Fun book on Goodreads
- Archived XSec releases page
- soshell Mirror
- Archived cloud-sec.org homepage
- Archived lengmo.net post
- Archived huaidan.org post
- Archived eviloctal forum post
- Mandiant APT41 report
- Archived WickedRose document
- AVIEN Malware Defense Guide PDF
- Justice Department APT41 press release
- FBI wanted page for APT 41
- USCC Adam Kozy testimony
- VirusTotal file analysis page
- BPFDoor dump
- Elastic BPFDoor configuration extractor
- Neo23x0 signature-base YARA rule
- Archived Just for Fun book on Archive.org
- Adore-ng GitHub repository
- Archived program details on Baidu blog