Linux 进程身份伪装
DARKCLOAK 将对所有用户空间可见身份来源的操纵串联成一个 11 阶段顺序流水线,逐步转换进程,直到对用户空间监控工具而言,它与被冒充的进程无法区分。据我们所知,尚无已发布的工具能够同时操纵所有用户空间可见的身份来源。
完整的技术文章可在 RAZOR 博客上获取。
task_struct->comm:通过 PR_SET_NAMEargv[0]:通过直接覆写栈/proc/$PID/cmdline):通过 PR_SET_MM_ARG_START/END/proc/$PID/environ):通过 PR_SET_MM_ENV_START/END/proc/$PID/exe):通过 PR_SET_MM_EXE_FILE/proc/$PID/maps):替换为匿名内存unshare该流水线按照被操纵内核子系统之间依赖关系所定义的严格顺序运行:
_start 处解析辅助向量以解析 PHT,并获取全部三个 PT_LOAD 段的虚拟地址范围getresuid / getresgid 以存储原始 UID 和 GID,供后续恢复setresuid(0,0,0)capget/capset 将 permitted 集合复制到 effective 和 inheritable 集合prctl(PR_SET_NAME) → 覆写 task_struct->comm[rsp+8] 处直接写栈 → 覆写 argv[0]prctl(PR_SET_DUMPABLE, 0) → 阻止非特权进程访问 /proc/$PID/mem 以及 只要仍有任何 VMA 由原始二进制文件支撑,PR_SET_MM_EXE_FILE 就会以 EBUSY 失败。由于当 RIP 位于 .text 段内部时无法取消映射该段,因此匿名化从临时匿名页运行:
mmap)mm_start→mm_end)和段元数据复制到其中mprotect).textPT_LOAD 段中的每一个:mmap 一个新的匿名区域 → memcpy 段内容 → munmap 原始段 → mremap 匿名副本回到原始地址 → mprotect 恢复原始权限.text,取消映射 trampoline 页该二进制文件是一个无解释器的静态 ELF,因此运行时 VMA 布局完全确定:三个 PT_LOAD 段、栈以及内核 vDSO。
nasm -f elf64 darkcloak.asm -o darkcloak.o
ld darkcloak.o -o darkcloak
伪造目标在编译时于 .data 段中定义。默认值冒充 sshd:
mimic_name db 'sshd', 0
mimic_argv db './sshd', 0
mimic_exe db '/usr/sbin/sshd', 0
mimic_cmdline db '/usr/sbin/sshd', 0, '-D', 0, '[email protected]', 0, ...
mimic_environ db 'LANG=en_US.UTF-8', 0, 'NOTIFY_SOCKET=/run/systemd/notify', 0, ...
要冒充其他进程,请在构建前更新这些值。
./darkcloak
需要在 permitted 集合中具备 CAP_SYS_RESOURCE、CAP_SETUID、CAP_SETGID 和 CAP_SETPCAP。如果缺少 CAP_SYS_RESOURCE,则完全跳过 MM 伪造块(VMA 匿名化 + EXE_FILE 交换)。如果缺少 CAP_SETPCAP,该工具会从 PR_SET_SECUREBITS 回退到 PR_SET_KEEPCAPS。
./darkcloak &
PID=$!
cat /proc/$PID/comm
readlink /proc/$PID/exe
cat /proc/$PID/cmdline | tr '\0' ' '
cat /proc/$PID/environ | tr '\0' '\n' | head -3
cat /proc/$PID/maps | head -5
cat /proc/$PID/status | grep -E 'Uid|Gid|Cap'
ps aux | grep $PID
仅出于教育和研究目的发布。仅可在您拥有或已获得明确书面授权进行测试的系统上使用。
ptrace(PTRACE_ATTACH)prctl(PR_SET_MM_ARG_START/END) → 重定向 /proc/$PID/cmdlineprctl(PR_SET_MM_ENV_START/END) → 重定向 /proc/$PID/environprctl(PR_SET_MM_EXE_FILE) → 替换 mm_struct->exe_filePR_SET_SECUREBITS(如果具备 CAP_SETPCAP)或 PR_SET_KEEPCAPS(回退方案)以在 UID 降权后继续存活setresuid(1000,1000,1000) 或恢复原始值setresgid(1000,1000,1000) 或恢复原始值unshare(CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC)nanosleep(120s) 然后 exit