基於python的局域網arp掃描

ARP協議

ARP 協議也叫作地址解析協議,就是IP地址轉換成MAC地址的協議python

原理:在局域網內廣播,向全部的主機發送包含目標IP地址的請求報文,若是該IP地址的主機接到了報文,那麼就會將本身的MAC地址返回給發送端。一樣根據這個原理就能夠實現掃描局域網的全部主機。bash

ARP請求報文

一個完整的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 地址測試

ARP發送

# 將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)

ARP監聽

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 "掃描結束"
相關文章
相關標籤/搜索