基于python的局域网arp扫描

ARP协议

ARP 协议也叫做地址解析协议,就是IP地址转换成MAC地址的协议

原理:在局域网内广播,向所有的主机发送包含目标IP地址的请求报文,如果该IP地址的主机接到了报文,那么就会将自己的MAC地址返回给发送端。同样根据这个原理就可以实现扫描局域网的所有主机。

ARP请求报文

一个完整的ARP数据报包括:14字节的以太网首部 + 28字节的ARP数据报

前者包括:6字节的目的MAC地址 + 6字节的发送端MAC地址 + 2字节的类型(0x0806:ARP协议)

后者包括: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 命令,查看对方的操作系统,例如:

~/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 "扫描结束"

 

转载于:https://my.oschina.net/u/2607780/blog/825995

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值