利用Python3的dpkt庫進行ARP掃描

背景

正在學習網絡協議,用Python寫起來方便點,能夠快速熟悉協議自己,也給本身補充一些Python庫。html

偶然看到這篇文章,講的是Python發ARP包,發現是Python2的,這裏改了一下,用Python3實現。python

  

環境

Ubuntu 18.04 + Python 3.6.5 + dpkt 1.9.1網絡

網絡相關信息見代碼部分。 socket

 

代碼

#!/usr/bin/python # -*- coding:utf-8 -*-

import dpkt import socket import sys import signal import ipaddress import struct 
my_iface = "ens33" my_mac = "00:0c:29:6a:f9:7e" my_ip = "192.168.93.151" sniff_network = "192.168.93.0/24" debug = False ETH_ADDR_BROADCAST = "ff:ff:ff:ff:ff:ff" ETH_ADDR_UNSPEC = "00:00:00:00:00:00" def eth_ntoa(buffer): mac_addr = '' for intval in struct.unpack("!BBBBBB", buffer): if intval > 15: replace_str = '0x' else: replace_str = 'x' # pythonic! mac_addr = ''.join([mac_addr, hex(intval).replace(replace_str, '')]) return mac_addr def eth_aton(buffer): intvals = buffer.split(':') rv = b'' for iv in intvals: rv += struct.pack("!B", int(iv, 16)) # 下面這種也行 # rv += bytes.fromhex(iv) return rv def build_arp(addr): arp_p = dpkt.arp.ARP() arp_p.sha = eth_aton(my_mac) arp_p.spa = socket.inet_aton(my_ip) arp_p.tha = eth_aton(ETH_ADDR_UNSPEC) arp_p.tpa = socket.inet_aton(addr) arp_p.op = dpkt.arp.ARP_OP_REQUEST packet = dpkt.ethernet.Ethernet() packet.src = eth_aton(my_mac) packet.dst = eth_aton(ETH_ADDR_BROADCAST) packet.type = dpkt.ethernet.ETH_TYPE_ARP packet.data = arp_p if debug: print(dpkt.hexdump(bytes(packet))) return packet # exits after 2 seconds def quit(sig_num, frame): print("Scan ended.") sys.exit(0) signal.alarm(2) signal.signal(signal.SIGALRM, quit) # build arp packet and send it one by one s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) s.bind((my_iface, dpkt.ethernet.ETH_TYPE_ARP)) for host in ipaddress.ip_network(sniff_network).hosts(): packet = build_arp(host.compressed) s.send(bytes(packet)) print('sniff host: ', host.compressed) # receive arp answer packets while True: data = s.recv(1024) if debug: print(dpkt.hexdump(data)) sys.stdout.flush() answer = dpkt.ethernet.Ethernet(data) answer_arp_p = answer.data answer_src_ip = socket.inet_ntoa(answer_arp_p.spa) answer_src_mac = eth_ntoa(answer_arp_p.sha) answer_dst_ip = socket.inet_ntoa(answer_arp_p.tpa) if debug: print(dpkt.hexdump(data)) if answer_arp_p.op != dpkt.arp.ARP_OP_REQUEST: if answer_dst_ip == my_ip: print("Answer: {0} is at {1}".format(answer_src_ip, my_mac))

 

測試

......
sniff host: 192.168.93.251 sniff host: 192.168.93.252 sniff host: 192.168.93.253 sniff host: 192.168.93.254 Answer: 192.168.93.2 is at 00:0c:29:6a:f9:7e Answer: 192.168.93.1 is at 00:0c:29:6a:f9:7e Answer: 192.168.93.160 is at 00:0c:29:6a:f9:7e Answer: 192.168.93.254 is at 00:0c:29:6a:f9:7e Scan ended.

 

引用

一篇講解dpkt庫和網絡協議的文章,很不錯,只是例子是Python2的。學習

DPKT CheatSheet測試

 

TODO

一開始用struct的pack/unpack實現,比較底層,能夠熟悉協議首部的構成和位、字節,無符號等概念。ui

高級點的,用dpkt,裏面把常見的協議都封裝成了對象,用起來也很方便。url

打算下一步再熟悉scapy,而後是Trex。spa

相關文章
相關標籤/搜索