用途限制声明,本文仅用于网络安全技术研究、教育与知识分享。文中涉及的渗透测试方法与工具,严禁用于未经授权的网络攻击、数据窃取或任何违法活动。任何因不当使用本文内容导致的法律后果,作者及发布平台不承担任何责任。渗透测试涉及复杂技术操作,可能对目标系统造成数据损坏、服务中断等风险。读者需充分评估技术能力与潜在后果,在合法合规前提下谨慎实践。
这次主要介绍通过python脚本构建ICMP隧道,从而能够进行隐藏通信,也是分为客户端和服务端,实操如下

代码如下
客户端源码
from scapy.all import IP, ICMP, send
import time
import argparse
import sys
def transmit(message, host, delay=0.1, verbose=False):
"""
通过ICMP协议传输消息,支持跨平台和复杂场景
:param message: 待传输的消息(支持非ASCII字符)
:param host: 目标主机IP地址
:param delay: 数据包发送间隔(秒),防止拥塞
:param verbose: 是否显示详细发送日志
"""
try:
# 1. 消息编码为UTF-8字节流(支持中文等非ASCII字符)
message_bytes = message.encode('utf-8')
# 2. 定义消息边界标识(避免与普通ICMP包混淆)
START_MARKER = b'\x02' # 开始标记(STX控制字符)
END_MARKER = b'\x03' # 结束标记(ETX控制字符)
# 3. 发送开始标记
send(IP(dst=host)/ICMP(code=START_MARKER[0]), verbose=0)
if verbose:
print(f"已发送开始标记到 {host}")
time.sleep(delay)
# 4. 发送消息字节(逐个字节发送)
for byte in message_bytes:
# 构建ICMP包(code字段存储字节值)
packet = IP(dst=host)/ICMP(code=byte)
send(packet, verbose=0) # verbose=0关闭scapy默认输出,跨平台一致
if verbose:
print(f"发送字节: 0x{byte:02x} ({chr(byte) if 32 <= byte <= 126 else '不可见字符'})")
time.sleep(delay) # 控制发送速率,避免接收端处理不及时
# 5. 发送结束标记
send(IP(dst=host)/ICMP(code=END_MARKER[0]), verbose=0)
if verbose:
print(f"已发送结束标记到 {host},消息传输完成")
except PermissionError:
# 跨平台权限处理提示
if sys.platform.startswith('win'):
print("错误:需要管理员权限运行(Windows)")
else:
print("错误:需要root权限运行(Linux/macOS)")
sys.exit(1)
except Exception as e:
print(f"发送失败:{str(e)}")
sys.exit(1)
if __name__ == "__main__":
# 命令行参数解析(支持灵活配置)
parser = argparse.ArgumentParser(description="通过ICMP协议传输消息(跨平台版)")
parser.add_argument("host", help="目标主机IP地址")
parser.add_argument("message", help="要传输的消息(支持中文等字符)")
parser.add_argument("-d", "--delay", type=float, default=0.1,
help="数据包发送间隔(秒),默认0.1s")
parser.add_argument("-v", "--verbose", action="store_true",
help="显示详细发送日志")
args = parser.parse_args()
# 执行传输
transmit(
message=args.message,
host=args.host,
delay=args.delay,
verbose=args.verbose
)
1. 模块导入部分
from scapy.all import IP, ICMP, send
import time
import argparse
import sys
scapy.all:导入 Scapy 库中的IP(用于构建 IP 层数据包)、ICMP(用于构建 ICMP 层数据包)、send(用于发送数据包),这是实现网络数据包构建和发送的核心工具。time:用于控制数据包发送间隔,避免发送过快导致拥塞。argparse:用于解析命令行参数,让用户可以通过命令行灵活配置目标主机、消息内容等。sys:用于处理系统相关操作(如判断操作系统类型、程序退出)。
2. 核心函数transmit定义
def transmit(message, host, delay=0.1, verbose=False):
"""
通过ICMP协议传输消息,支持跨平台和复杂场景
:param message: 待传输的消息(支持非ASCII字符)
:param host: 目标主机IP地址
:param delay: 数据包发送间隔(秒),防止拥塞
:param verbose: 是否显示详细发送日志
"""
这是整个程序的核心函数,用于实现消息通过 ICMP 协议的传输。函数参数说明:
message:需要传输的文本内容(支持中文、特殊符号等非 ASCII 字符)。host:目标主机的 IP 地址(消息要发送到的设备)。delay:数据包之间的发送间隔(默认 0.1 秒),避免发送过快导致接收端处理不及时。verbose:是否打印详细日志(如发送的每个字节内容),方便调试。
3. 消息处理与标记定义
try:
# 1. 消息编码为UTF-8字节流(支持中文等非ASCII字符)
message_bytes = message.encode('utf-8')
# 2. 定义消息边界标识(避免与普通ICMP包混淆)
START_MARKER = b'\x02' # 开始标记(STX控制字符,ASCII码中的"文本开始")
END_MARKER = b'\x03' # 结束标记(ETX控制字符,ASCII码中的"文本结束")
- 消息编码:将输入的文本
message通过utf-8编码为字节流(bytes类型),确保中文、日文等非 ASCII 字符能正确传输(文本在网络中传输必须转为字节形式)。 - 边界标记:定义了
START_MARKER(开始标记)和END_MARKER(结束标记),使用 ASCII 控制字符(非打印字符),目的是区分 "我们传输的消息包" 和网络中普通的 ICMP 包(如正常 ping 命令的包),让接收端能识别消息的开始和结束。
4. 消息发送流程
(1)发送开始标记
# 3. 发送开始标记
send(IP(dst=host)/ICMP(code=START_MARKER[0]), verbose=0)
if verbose:
print(f"已发送开始标记到 {host}")
time.sleep(delay)
- 构建数据包:
IP(dst=host)指定目标主机 IP,ICMP(code=START_MARKER[0])构建 ICMP 包,将开始标记的字节值存入 ICMP 的code字段(ICMP 协议的code字段本用于表示消息类型细分,这里被复用为传输数据的载体)。 - 发送与延迟:通过
send函数发送数据包,verbose=0关闭 Scapy 的默认输出;发送后根据delay参数等待一段时间,再发送下一个包。
(2)发送消息字节(核心传输逻辑)
# 4. 发送消息字节(逐个字节发送)
for byte in message_bytes:
# 构建ICMP包(code字段存储字节值)
packet = IP(dst=host)/ICMP(code=byte)
send(packet, verbose=0) # 关闭默认输出,跨平台一致
if verbose:
print(f"发送字节: 0x{byte:02x} ({chr(byte) if 32 <= byte <= 126 else '不可见字符'})")
time.sleep(delay) # 控制发送速率
- 逐个字节发送:将编码后的消息字节流(
message_bytes)按顺序逐个取出,每个字节的值存入 ICMP 包的code字段,再封装到 IP 包中发送。 - 日志输出:如果
verbose为True,会打印每个字节的十六进制值(如0x61对应字符a)和对应的可见字符(不可见字符会标注)。 - 速率控制:每个字节发送后等待
delay时间,避免发送过快导致接收端漏包。
(3)发送结束标记
# 5. 发送结束标记
send(IP(dst=host)/ICMP(code=END_MARKER[0]), verbose=0)
if verbose:
print(f"已发送结束标记到 {host},消息传输完成")
- 消息传输完成后,发送结束标记(
END_MARKER),告知接收端 "当前消息已全部传输完毕"。
5. 异常处理
except PermissionError:
# 跨平台权限处理提示
if sys.platform.startswith('win'):
print("错误:需要管理员权限运行(Windows)")
else:
print("错误:需要root权限运行(Linux/macOS)")
sys.exit(1)
except Exception as e:
print(f"发送失败:{str(e)}")
sys.exit(1)
PermissionError:发送 ICMP 包需要管理员 /root 权限(网络底层操作的限制),捕获该异常后,根据操作系统类型(Windows/Linux/macOS)提示用户获取对应权限。- 其他异常:捕获所有其他可能的错误(如网络不可达、目标主机无响应等),打印错误信息并退出程序。
6. 命令行参数解析(程序入口)
if __name__ == "__main__":
# 命令行参数解析(支持灵活配置)
parser = argparse.ArgumentParser(description="通过ICMP协议传输消息(跨平台版)")
parser.add_argument("host", help="目标主机IP地址")
parser.add_argument("message", help="要传输的消息(支持中文等字符)")
parser.add_argument("-d", "--delay", type=float, default=0.1,
help="数据包发送间隔(秒),默认0.1s")
parser.add_argument("-v", "--verbose", action="store_true",
help="显示详细发送日志")
args = parser.parse_args()
# 执行传输
transmit(
message=args.message,
host=args.host,
delay=args.delay,
verbose=args.verbose
)
- 程序入口逻辑:当脚本直接运行时(而非被导入为模块),通过
argparse解析命令行参数。 - 参数定义:
- 必选参数:
host(目标 IP)和message(要传输的消息)。 - 可选参数:
-d/--delay(发送间隔)、-v/--verbose(详细日志开关)。
- 必选参数:
- 执行传输:解析参数后,调用
transmit函数,将命令行输入的参数传入,开始消息传输。
服务端源码
from scapy.all import sniff, ICMP, IP
import argparse
import sys
import time
class ICMPMessageReceiver:
def __init__(self, src_ip=None, verbose=False, timeout=30):
"""
ICMP消息接收管理器
:param src_ip: 仅接收来自该IP的消息(None表示接收所有)
:param verbose: 是否显示详细日志
:param timeout: 消息超时时间(秒),超过时间未收到结束标记则重置
"""
self.src_ip = src_ip
self.verbose = verbose
self.timeout = timeout
self.current_bytes = [] # 缓存当前消息的字节流
self.is_receiving = False # 是否处于接收消息状态
self.last_packet_time = time.time() # 最后收到数据包的时间
# 消息边界标记(与客户端对应)
self.START_MARKER = 0x02 # STX控制字符
self.END_MARKER = 0x03 # ETX控制字符
def process_packet(self, packet):
"""处理捕获到的ICMP数据包"""
# 检查是否为ICMP包
if not packet.haslayer(ICMP):
return
# 过滤源IP(如果指定)
if self.src_ip and packet[IP].src != self.src_ip:
if self.verbose:
print(f"忽略来自 {packet[IP].src} 的非目标数据包", file=sys.stderr)
return
# 获取ICMP包的code字段(字节值)
icmp_code = packet[ICMP].code
self.last_packet_time = time.time()
# 处理开始标记
if icmp_code == self.START_MARKER:
if self.is_receiving:
if self.verbose:
print("\n警告:收到新的开始标记,但上一条消息未结束,强制重置", file=sys.stderr)
self.current_bytes = []
self.is_receiving = True
if self.verbose:
print(f"\n开始接收来自 {packet[IP].src} 的消息...", file=sys.stderr)
return
# 处理结束标记
if icmp_code == self.END_MARKER and self.is_receiving:
self.is_receiving = False
try:
# 将字节流解码为UTF-8字符串(支持中文等非ASCII字符)
message = bytes(self.current_bytes).decode('utf-8')
print(f"\n收到完整消息:{message}")
if self.verbose:
print(f"消息长度:{len(self.current_bytes)}字节,来源:{packet[IP].src}", file=sys.stderr)
except UnicodeDecodeError:
print(f"\n错误:消息解码失败(非UTF-8格式),原始字节:{self.current_bytes}", file=sys.stderr)
finally:
self.current_bytes = [] # 重置缓存
return
# 接收消息内容(仅在接收状态下处理)
if self.is_receiving:
self.current_bytes.append(icmp_code)
if self.verbose:
# 显示字节信息(可见字符显示字符,不可见显示十六进制)
char = chr(icmp_code) if 32 <= icmp_code <= 126 else f"0x{icmp_code:02x}"
print(f"接收字节:{char}(累计{len(self.current_bytes)}字节)", file=sys.stderr)
def check_timeout(self):
"""检查消息超时(后台线程调用)"""
while True:
if self.is_receiving and (time.time() - self.last_packet_time) > self.timeout:
print(f"\n超时警告:超过{self.timeout}秒未收到消息,重置接收状态", file=sys.stderr)
self.is_receiving = False
self.current_bytes = []
time.sleep(1)
def main():
# 命令行参数解析
parser = argparse.ArgumentParser(description="ICMP消息接收服务器(跨平台版)")
parser.add_argument("-s", "--src-ip", help="仅接收来自该IP的消息(可选)")
parser.add_argument("-v", "--verbose", action="store_true", help="显示详细接收日志")
parser.add_argument("-t", "--timeout", type=int, default=30, help="消息超时时间(秒),默认30s")
args = parser.parse_args()
# 初始化接收器
receiver = ICMPMessageReceiver(
src_ip=args.src_ip,
verbose=args.verbose,
timeout=args.timeout
)
# 启动超时检查线程
import threading
timeout_thread = threading.Thread(target=receiver.check_timeout, daemon=True)
timeout_thread.start()
try:
print("ICMP消息服务器启动,等待消息...(按Ctrl+C退出)")
# 过滤ICMP包,仅处理类型为8(请求)或0(响应)的包(兼容多数场景)
sniff(
filter="icmp and (icmp[0] == 8 or icmp[0] == 0)",
prn=receiver.process_packet,
store=0 # 不缓存数据包,节省内存
)
except PermissionError:
# 跨平台权限提示
if sys.platform.startswith('win'):
print("错误:需要管理员权限运行(Windows)", file=sys.stderr)
else:
print("错误:需要root权限运行(Linux/macOS)", file=sys.stderr)
sys.exit(1)
except KeyboardInterrupt:
print("\n服务器已手动停止")
sys.exit(0)
except Exception as e:
print(f"服务器异常:{str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
1. 模块导入部分
from scapy.all import sniff, ICMP, IP
import argparse
import sys
import time
scapy.all:导入sniff(用于捕获网络数据包)、ICMP(解析 ICMP 层数据)、IP(解析 IP 层数据),是实现数据包捕获和解析的核心工具。argparse:解析命令行参数,让用户可配置接收规则(如指定源 IP、超时时间等)。sys:处理系统相关操作(如输出错误信息、程序退出)。time:用于记录数据包接收时间,实现超时检测。
2. ICMPMessageReceiver类(核心接收逻辑)
这是接收端的核心类,封装了消息接收、解析、超时处理等功能。
(1)初始化方法__init__
def __init__(self, src_ip=None, verbose=False, timeout=30):
"""
ICMP消息接收管理器
:param src_ip: 仅接收来自该IP的消息(None表示接收所有)
:param verbose: 是否显示详细日志
:param timeout: 消息超时时间(秒),超过时间未收到结束标记则重置
"""
self.src_ip = src_ip # 源IP过滤条件(可选)
self.verbose = verbose # 详细日志开关
self.timeout = timeout # 超时时间(默认30秒)
self.current_bytes = [] # 缓存当前接收的字节流
self.is_receiving = False # 标记是否处于接收消息状态
self.last_packet_time = time.time() # 最后收到数据包的时间(用于超时判断)
# 消息边界标记(与发送端完全一致,确保能正确识别)
self.START_MARKER = 0x02 # STX控制字符(对应发送端的b'\x02')
self.END_MARKER = 0x03 # ETX控制字符(对应发送端的b'\x03')
- 初始化接收端的核心参数和状态变量:
- 过滤条件(
src_ip):只接收指定 IP 的消息,提高安全性。 - 状态管理(
current_bytes、is_receiving):缓存接收的字节,标记是否正在接收消息(避免混淆多个消息)。 - 超时控制(
last_packet_time、timeout):记录最后一个包的时间,用于检测消息是否中断。 - 边界标记(
START_MARKER、END_MARKER):与发送端严格一致,确保能正确识别消息的开始和结束。
- 过滤条件(
(2)数据包处理方法process_packet
这是处理每个捕获到的数据包的核心逻辑,负责解析 ICMP 包并提取消息:
def process_packet(self, packet):
"""处理捕获到的ICMP数据包"""
# 1. 过滤非ICMP包(只处理ICMP协议的包)
if not packet.haslayer(ICMP):
return
# 2. 过滤源IP(如果指定了src_ip,只处理来自该IP的包)
if self.src_ip and packet[IP].src != self.src_ip:
if self.verbose:
print(f"忽略来自 {packet[IP].src} 的非目标数据包", file=sys.stderr)
return
# 3. 提取ICMP包的code字段(发送端存储字节数据的位置)
icmp_code = packet[ICMP].code
self.last_packet_time = time.time() # 更新最后接收时间(重置超时计时)
- 第一步过滤非 ICMP 包:只处理 ICMP 协议的数据包(因为消息通过 ICMP 传输)。
- 第二步过滤源 IP:如果用户指定了
src_ip,则忽略其他 IP 的包(避免接收无关消息)。 - 第三步提取数据:从 ICMP 包的
code字段中取出字节值(发送端正是将数据存在这里),并更新最后接收时间(避免超时误判)。
# 4. 处理开始标记(收到START_MARKER时,准备接收新消息)
if icmp_code == self.START_MARKER:
if self.is_receiving:
# 如果正在接收消息却又收到新的开始标记,说明上一条消息异常中断,强制重置
if self.verbose:
print("\n警告:收到新的开始标记,但上一条消息未结束,强制重置", file=sys.stderr)
self.current_bytes = [] # 清空缓存
self.is_receiving = True # 标记为接收状态
if self.verbose:
print(f"\n开始接收来自 {packet[IP].src} 的消息...", file=sys.stderr)
return
- 当收到开始标记(
START_MARKER)时:- 如果正在接收其他消息(
is_receiving=True),说明上一条消息可能异常中断,强制重置缓存。 - 初始化缓存(
current_bytes),标记为接收状态(is_receiving=True),准备接收新消息。
- 如果正在接收其他消息(
# 5. 处理结束标记(收到END_MARKER且处于接收状态时,完成消息接收)
if icmp_code == self.END_MARKER and self.is_receiving:
self.is_receiving = False # 标记为非接收状态
try:
# 将字节流解码为UTF-8字符串(与发送端的编码方式对应)
message = bytes(self.current_bytes).decode('utf-8')
print(f"\n收到完整消息:{message}") # 打印最终消息
if self.verbose:
print(f"消息长度:{len(self.current_bytes)}字节,来源:{packet[IP].src}", file=sys.stderr)
except UnicodeDecodeError:
# 处理解码失败(如发送端编码方式与接收端不一致)
print(f"\n错误:消息解码失败(非UTF-8格式),原始字节:{self.current_bytes}", file=sys.stderr)
finally:
self.current_bytes = [] # 重置缓存,准备接收下一条消息
return
- 当收到结束标记(
END_MARKER)且处于接收状态时:- 结束接收(
is_receiving=False),将缓存的字节流(current_bytes)通过 UTF-8 解码为文本(与发送端的encode('utf-8')对应)。 - 处理可能的解码错误(如发送的字节流不是 UTF-8 格式),最后重置缓存
- 结束接收(
# 6. 接收消息内容(仅在接收状态下,收集字节数据)
if self.is_receiving:
self.current_bytes.append(icmp_code) # 将字节存入缓存
if self.verbose:
# 显示详细信息:可见字符直接显示,不可见字符显示十六进制
char = chr(icmp_code) if 32 <= icmp_code <= 126 else f"0x{icmp_code:02x}"
print(f"接收字节:{char}(累计{len(self.current_bytes)}字节)", file=sys.stderr)
- 在接收状态(
is_receiving=True)下,将每个 ICMP 包的code值(字节)存入缓存,逐步拼接完整消息。 - 详细日志模式下,会显示每个字节的信息(可见字符直接显示,不可见字符显示十六进制,方便调试)。
(3)超时检查方法check_timeout
def check_timeout(self):
"""检查消息超时(后台线程调用)"""
while True:
# 如果正在接收消息,且距离最后一个包的时间超过超时时间
if self.is_receiving and (time.time() - self.last_packet_time) > self.timeout:
print(f"\n超时警告:超过{self.timeout}秒未收到消息,重置接收状态", file=sys.stderr)
self.is_receiving = False # 重置接收状态
self.current_bytes = [] # 清空缓存
time.sleep(1) # 每秒检查一次
- 这是一个后台循环方法,用于检测消息是否超时:
- 每隔 1 秒检查一次,如果处于接收状态,且超过
timeout时间未收到新包,说明消息可能中断(如网络故障)。 - 此时重置接收状态和缓存,避免一直处于 "接收中" 状态,无法接收新消息。
- 每隔 1 秒检查一次,如果处于接收状态,且超过
3. 主函数main(程序入口)
def main():
# 1. 解析命令行参数
parser = argparse.ArgumentParser(description="ICMP消息接收服务器(跨平台版)")
parser.add_argument("-s", "--src-ip", help="仅接收来自该IP的消息(可选)")
parser.add_argument("-v", "--verbose", action="store_true", help="显示详细接收日志")
parser.add_argument("-t", "--timeout", type=int, default=30, help="消息超时时间(秒),默认30s")
args = parser.parse_args()
- 通过
argparse解析用户输入的命令行参数:-s/--src-ip:可选参数,指定只接收来自该 IP 的消息。-v/--verbose:可选开关,开启后显示详细日志。-t/--timeout:可选参数,设置超时时间(默认 30 秒)。
# 2. 初始化接收器
receiver = ICMPMessageReceiver(
src_ip=args.src_ip,
verbose=args.verbose,
timeout=args.timeout
)
# 3. 启动超时检查线程(后台运行)
import threading
timeout_thread = threading.Thread(target=receiver.check_timeout, daemon=True)
timeout_thread.start()
- 初始化
ICMPMessageReceiver实例,传入解析后的参数。 - 启动超时检查线程:将
check_timeout方法作为线程目标,daemon=True表示该线程随主线程退出而结束(避免程序无法正常退出)。
try:
print("ICMP消息服务器启动,等待消息...(按Ctrl+C退出)")
# 4. 捕获并处理ICMP数据包
sniff(
filter="icmp and (icmp[0] == 8 or icmp[0] == 0)", # 过滤规则:只捕获ICMP请求(8)或响应(0)包
prn=receiver.process_packet, # 每个包都交给process_packet处理
store=0 # 不缓存数据包(节省内存,适合长时间运行)
)
- 核心:通过
sniff函数捕获网络数据包,过滤规则为 "ICMP 协议,且类型为 8(请求)或 0(响应)"(覆盖大多数 ICMP 场景,与发送端兼容)。 prn=receiver.process_packet:指定每个捕获到的包都由process_packet方法处理。store=0:不缓存数据包,避免长时间运行导致内存占用过高。
except PermissionError:
# 权限异常处理(与发送端一致,需要管理员/root权限)
if sys.platform.startswith('win'):
print("错误:需要管理员权限运行(Windows)", file=sys.stderr)
else:
print("错误:需要root权限运行(Linux/macOS)", file=sys.stderr)
sys.exit(1)
except KeyboardInterrupt:
# 手动中断处理(用户按Ctrl+C)
print("\n服务器已手动停止")
sys.exit(0)
except Exception as e:
# 其他异常处理
print(f"服务器异常:{str(e)}", file=sys.stderr)
sys.exit(1)
- 异常处理:
PermissionError:捕获权限不足的错误,根据操作系统提示需要管理员 /root 权限(与发送端一致)。KeyboardInterrupt:捕获用户手动中断(Ctrl+C),友好提示并退出。- 其他异常:打印错误信息并退出,确保程序稳定。
在我的上一篇文章中,Python 实战:内网渗透中的信息收集自动化脚本(7)-CSDN博客讲述了通过http协议构建C2通道,这篇我们是通过ICMP协议构建的通道,那么有什么不同呢
| 维度 | ICMP 消息传输代码 | C2 系统代码 |
|---|---|---|
| 核心用途 | 单向 / 简单的消息传输(如文本消息传递) | 复杂的命令与控制(C2)场景(客户端与服务器持续交互、远程命令执行) |
| 底层协议 | 基于 ICMP 协议(网络层,通常用于网络诊断,如 ping) | 基于 HTTP/HTTPS 协议(应用层,基于 TCP) |
| 功能复杂度 | 功能简单:仅支持消息编码(UTF-8)、边界标记(开始 / 结束符)传输 | 功能丰富:支持加密、认证、重试、故障转移、轮询、命令执行与结果返回等 |
| 安全性 | 无加密 / 认证:消息通过 ICMP 的code字段明文传输,易被拦截解析 | 多层安全:数据加密(Fernet)、身份认证(Bearer Token)、HTTPS 传输加密 |
| 通信模式 | 单向传输:客户端发送消息,服务器被动接收,无交互反馈 | 双向交互:客户端发送命令 / 状态,服务器返回指令,支持持续轮询 |
| 可靠性保障 | 无重试 / 容错:ICMP 无连接特性,丢包后无法恢复,依赖超时重置 | 多重保障:重试机制(失败重连)、故障转移(多服务器 URL)、超时控制 |
| 隐蔽性设计 | 依赖 ICMP 协议的普遍性(易被忽略),无额外隐蔽措施 | 主动隐蔽:随机化轮询间隔、备用传输方式(Cookie)、伪装 User-Agent |
各自优劣分析
1. ICMP 消息传输代码(client.py + server.py)
优势:
- 隐蔽性较强:ICMP 是网络诊断常用协议(如 ping),其流量不易被特殊关注,适合简单隐蔽通信。
- 实现简单:代码逻辑直接,无需处理复杂的应用层协议细节(如 HTTP 请求 / 响应、会话管理)。
- 轻量高效:仅传输必要字节流,资源消耗低,适合简单文本消息传输。
劣势:
- 功能单一:仅支持单向消息传输,无交互能力,无法满足复杂场景(如命令执行、结果反馈)。
- 安全性差:消息明文传输(ICMP 的
code字段直接存储字节),无加密或身份验证,易被窃听或伪造。 - 可靠性低:ICMP 是无连接协议,无重传机制,丢包会导致消息损坏;依赖超时重置,容错能力弱。
- 权限要求高:发送 / 捕获 ICMP 包需要 root(Linux/macOS)或管理员权限(Windows),部署受限。
2. C2 系统代码(client1.py + server1.py)
优势:
- 功能强大:支持双向交互、命令执行、结果返回、持续轮询等,满足复杂的远程控制需求。
- 安全性高:通过 Fernet 加密数据、Bearer Token 认证身份、HTTPS 传输加密,大幅降低数据泄露和伪造风险。
- 可靠性强:内置重试机制、多服务器故障转移、超时控制,确保网络不稳定时仍能通信。
- 灵活性高:支持代理配置、备用传输方式(Cookie)、自定义 User-Agent,适应不同网络环境。
劣势:
- 隐蔽性较弱:HTTP/HTTPS 流量虽常见,但频繁的 C2 通信(尤其是固定间隔轮询)可能被安全设备检测。
- 实现复杂:代码包含大量模块(配置、加密、会话、重试等),开发和维护成本高。
- 资源消耗高:相比 ICMP,HTTPS 握手、加密解密、会话管理会消耗更多 CPU 和网络资源。
适用场景
- ICMP 代码:适合简单、轻量、对隐蔽性要求高的单向消息传输(如跨网络传递短文本)。
- C2 代码:适合需要双向交互、高安全性、高可靠性的远程控制场景(如服务器管理、设备监控)。
ICMP也可以构建类似于http协议构建的C2通道,但是其应用性和隐蔽性弱于http协议,http属于应用层协议,而ICMP严格上来说属于网络层协议,层级在一定程度上限制了协议的使用。所以说,
- ICMP 作为 C2 通道:可行但 “性价比低”,仅适合极端场景(如目标网络仅开放 ICMP),需突破协议限制才能实现基础双向交互,且隐蔽性和应用性均受限。
- HTTP 作为 C2 通道:天然适配 C2 的功能需求,借助成熟的应用层特性可快速实现高安全性、高可靠性的控制逻辑,隐蔽性在多数场景下更优。

被折叠的 条评论
为什么被折叠?



