ARP 協議也叫作地址解析協議,就是IP地址轉換成MAC地址的協議python
原理:在局域網內廣播,向全部的主機發送包含目標IP地址的請求報文,若是該IP地址的主機接到了報文,那麼就會將本身的MAC地址返回給發送端。一樣根據這個原理就能夠實現掃描局域網的全部主機。bash
一個完整的ARP數據報包括:14字節的以太網首部 + 28字節的ARP數據報網絡
前者包括:6字節的目的MAC地址 + 6字節的發送端MAC地址 + 2字節的類型(0x0806:ARP協議)socket
後者包括:2B 硬件類型+2B 協議類型+1B 硬件地址長度+1B協議地址長度+2B 操做類型+6B 發送端 MAC 地址+4B 發送端 IP 地址+6B 目的端 MAC 地址+4B 目的端 IP 地址測試
# 將16進制的MAC地址轉換成,須要的字符格式 def mac2a(m): return binascii.a2b_hex(m) # 將ip地址列表轉換成,須要的字符格式 def ip2a(i): ipi = i[0]*256*256*256+i[1]*256*256+i[2]*256+i[3] iph = hex(ipi) return binascii.a2b_hex(iph[2:]) # 向指定IP發送ARP報 def send(ip): # 設置協議族類型和上層協議 rawS = socket.socket(socket.PF_PACKET,socket.SOCK_RAW, socket.htons(0x0806)) # 綁定網卡和端口號 rawS.bind(("wlo1",socket.htons(0x0800))) # 以太網頭封包,6s:6B的目的端MAC,6s:6B 發送端MAC,2s:2B的協議類型 tha = mac2a('ffffffffffff') #target hardware address 目的端硬件地址 sha = mac2a('34238769543e') #sender hardware address 發送端硬件地址 ethHdr = tha+sha+'\x08\x06' # ARP數據封包 hrd = '\x00\x01' #硬件地址類型,默認1:以太網 pro = '\x08\x00' #網絡地址類型,0800:IP地址 hln = '\x06' #硬件地址長度,單位B pln = '\x04' #網絡地址長度,單位B op = '\x00\x01' #操做類型,1:arp請求,2:arp響應 #sha = sha #發送端硬件地址 spa = ip2a([192,168,199,112]) #發送端網絡地址 #tha = tha #目的端硬件地址 tpa = ip2a(ip) #目的端網絡地址 arpPkt = hrd+pro+hln+pln+op+sha+spa+tha+tpa # 發送 rawS.send(ethHdr+arpPkt)
def a2ip(a): return '%d.%d.%d.%d'%tuple(map(ord,list(a))) def a2mac(a): h = binascii.b2a_hex(a) return ':'.join([h[i:i+2] for i in xrange(0,len(h),2)]) #監聽ARP響應 def listen(): pc=pcap.pcap("wlo1") #注,參數可爲網卡名,如eth0 for pt,pd in pc: #pt爲收到時間,pd爲收到數據 eth = dpkt.ethernet.Ethernet(pd) if eth.type==2054: arp = eth.data if arp.op==2: #ARP響應 print "在線",a2ip(arp.spa)," ",a2mac(arp.sha)
~/python/pcap/arp$ sudo python lanScan.py 掃描開始 在線 192.168.199.1 d4:ee:07:1b:71:9c 在線 192.168.199.135 fc:64:ba:04:e0:2f 在線 192.168.199.148 90:00:4e:1e:19:ba 在線 192.168.199.153 a0:88:69:9d:ef:3b 在線 192.168.199.154 84:9f:b5:41:aa:f1 在線 192.168.199.154 84:9f:b5:41:aa:f1 在線 192.168.199.164 24:fd:52:92:14:86 掃描結束 ~/python/pcap/arp$
這樣就可已知道全部的局域網的主機了,也能夠使用 ping 命令,查看對方的操做系統,例如:spa
~/python/pcap/arp$ ping 192.168.199.1 PING 192.168.199.1 (192.168.199.1) 56(84) bytes of data. 64 bytes from 192.168.199.1: icmp_seq=1 ttl=64 time=1.69 ms 64 bytes from 192.168.199.1: icmp_seq=2 ttl=64 time=1.20 ms # 主要看ttl字段,通常狀況下 # Linux系統的TTL值爲64或255 # Windows NT/2000/XP系統的TTL值爲128 # Windows 98系統的TTL值爲32 # UNIX主機的TTL值爲255
#!/usr/bin/python # -*- coding: UTF-8 -*- # sendARP.py # 探測局域網 IP import socket import struct import binascii import dpkt import pcap import thread # 將16進制的MAC地址轉換成,須要的字符格式 def mac2a(m): return binascii.a2b_hex(m) # 將ip地址列表轉換成,須要的字符格式 def ip2a(i): ipi = i[0]*256*256*256+i[1]*256*256+i[2]*256+i[3] iph = hex(ipi) return binascii.a2b_hex(iph[2:]) # 向指定IP發送ARP報 def send(ip): # 設置協議族類型和上層協議 rawS = socket.socket(socket.PF_PACKET,socket.SOCK_RAW, socket.htons(0x0806)) # 綁定網卡和端口號 rawS.bind(("wlo1",socket.htons(0x0800))) # 以太網頭封包,6s:6B的目的端MAC,6s:6B 發送端MAC,2s:2B的協議類型 tha = mac2a('ffffffffffff') #target hardware address 目的端硬件地址 sha = mac2a('34238769543e') #sender hardware address 發送端硬件地址 ethHdr = tha+sha+'\x08\x06' # ARP數據封包 hrd = '\x00\x01' #硬件地址類型,默認1:以太網 pro = '\x08\x00' #網絡地址類型,0800:IP地址 hln = '\x06' #硬件地址長度,單位B pln = '\x04' #網絡地址長度,單位B op = '\x00\x01' #操做類型,1:arp請求,2:arp響應 #sha = sha #發送端硬件地址 spa = ip2a([192,168,199,112]) #發送端網絡地址 #tha = tha #目的端硬件地址 tpa = ip2a(ip) #目的端網絡地址 arpPkt = hrd+pro+hln+pln+op+sha+spa+tha+tpa # 發送 rawS.send(ethHdr+arpPkt) def a2ip(a): return '%d.%d.%d.%d'%tuple(map(ord,list(a))) def a2mac(a): h = binascii.b2a_hex(a) return ':'.join([h[i:i+2] for i in xrange(0,len(h),2)]) #監聽ARP響應 def listen(): pc=pcap.pcap("wlo1") #注,參數可爲網卡名,如eth0 for pt,pd in pc: #pt爲收到時間,pd爲收到數據 eth = dpkt.ethernet.Ethernet(pd) if eth.type==2054: arp = eth.data if arp.op==2: #ARP響應 print "在線",a2ip(arp.spa)," ",a2mac(arp.sha) #listen() thread.start_new_thread(listen,()) print "掃描開始" for i in xrange(1,255): send([192,168,199,i]) print "掃描結束"