上网除了需要 IP, 还需要 Mac 地址, Mac 与网卡绑定, 我们记录了设备的 Mac, 相当于标记了设备使用者
关于 Mac 和 IP 的关系: <讲个故事>为什么 IP 地址与 Mac 地址缺一不可?
星巴克
初级玩法: 哪个时段顾客人数最多?
今天放假, 人格外多, 想统计一下有多少台设备在上网(有多少 IP 被占用)
原理: 批量发送 ping, 按照协议, 对方会对我们的 ping, 产生应答, 然后记录应答的 ip
- from scapy.all import *
- for i in range(100):
- # 生成目标 IP
- ip = "192.168.31."+str(i)
- # 打印生成的目标 IP
- print("= 目标 ip 为 =>", ip)
- # 根据目标 IP 组包, ICMP 可以看做 Ping
- p = IP(dst=ip)/ICMP()
- # 将数据包发出, 等待 0.5 秒, 无回应则放弃等待
- r = sr1(p, timeout=0.5)
神器 wireshark 查看结果
ip.dst == 192.168.31.19 and (ip.src>= 192.168.31.1 and 192.168.31.255>= ip.src)
关于 wireshark 的使用: "杀手级" 抓包软件 wireshark 入门
进阶玩法: 今天来了几名新顾客? (信息自动化编程实现局域网扫描)
功能 1: 针对不同网段扫描
我的计算机内存在两个虚拟路由器(同时安装了 Parallels, Vmware, 两个网段), 同时我连接了公共场所的无线网(一个网段), 编程实现自动识别三个网段, 可选择性的扫描
选择网段
功能 2: 记录在线设备的 mac 地址
初级的玩法是记录 ip(网络层), 既然是高级玩法, 我们把 Mac 地址 (数据链路层) 也记录下来
记录 Mac 地址
功能 3: 将 mac 地址转换为网卡厂商
wireshark 实现了这个功能, 这个功能的实现原理就是查字典, 我这里就直接从 github 找了一个专门翻译 mac 地址的库仓库
value
功能 4: 保存结果:
程序会以完成的时间作为文件吗, 将分析结果保存到同级目录下
保存的结果
功能 5: 开启多线程?
这个程序默认设置的是 0.2 秒的等待, 如果收不到回应, 就转到下一个 IP, 如果开启了多线程, 平均时间会更短, 但抱着不作恶的宗旨, 这里就不放了
运行界面
- import os
- import re
- from scapy.all import *
- from scapy.layers import l2
- import json
- import time
- from macpy import Mac
- # A 类地址: 10.0.0.0--10.255.255.255
- # B 类地址: 172.16.0.0--172.31.255.255
- # C 类地址: 192.168.0.0--192.168.255.255
- def get_all_ip_range():
- result = []
- ip_des_list = os.popen("ifconfig | grep inet").readlines()
- for ip_des in ip_des_list:
- try:
- if re.match(r'\tinet[^6]([0-9]{1,3}).*', ip_des).group(1) in ["192", "172", "10"]:
- ip_des = re.match(r'\tinet[^6]([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*', ip_des).group(1)
- ip_range = re.match(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.', ip_des).group()
- result.append(ip_range)
- except:
- pass
- return result
- def getIPAndMac(ip_range):
- result_list = {}
- for ip in ip_range:
- # 打印生成的目标 IP
- print("= 检测 ip=>", ip)
- # 根据目标 IP 组包, ICMP 可以看做 Ping, 程序员式招呼
- p = IP(dst=ip)/ICMP()/b'HelloWorld'
- # 将数据包发出, 等待 0.3 秒, 无回应则放弃等待, 屏蔽提示消息
- r = sr1(p, timeout=0.3, verbose = False)
- # 如果收到了返回的数据包, 则存到一个数组中
- try:
- if r.getlayer(IP).fields['src'] == ip and r.getlayer(ICMP).fields['type'] == 0:
- net_info = {}
- mac = l2.getmacbyip(ip)
- getcom = Mac()
- com = getcom.search(mac)
- mac = mac+ "|" + str(com)
- result_list[str(ip)] = mac
- print("成功获取一个 mac 地址:", ip, mac)
- except Exception as e:
- pass
- return result_list
- def select_ip_range(all_ip_range):
- choose_ip_dic = {}
- for index, ip_range in enumerate(all_ip_range):
- all_ip = []
- for num in range(256):
- all_ip.append(ip_range+str(num))
- choose_ip_dic[index] = all_ip
- index_list = []
- for index, ip_range in enumerate(all_ip_range):
- index_list.append(index)
- print("序列号:", index, "ip 范围", ip_range+"0"+"-"+ip_range+"255")
- print(index_list)
- while 1:
- user_choose = input("请输入您需要扫描的 ip 范围序号:")
- try:
- user_choose = int(user_choose)
- except:
- print("请您输入数字!!!")
- pass
- if user_choose in index_list:
- user_ip_list = choose_ip_dic[int(user_choose)]
- break
- else:
- print("您的输入有误, 请查正后输入!!!")
- return user_ip_list
- def genderTxt(result_dic):
- file_name = time.strftime("%Y%m%d%H%M%S")+"IPAndMac.txt"
- print(file_name)
- for key in result_dic:
- with open(file_name, "a") as f:
- f.write("设备的 IP:"+key+"Mac 地址"+result_dic[key]+"\n")
- result_json = json.dumps(result_dic, ensure_ascii=False)
- def main():
- all_ip_range = get_all_ip_range()
- ip_range = select_ip_range(all_ip_range)
- print(ip_range)
- result_dic = getIPAndMac(ip_range)
- # result_dic = {"k1": "001", "k123": "msdf", "k213": "00213"}
- genderTxt(result_dic)
- if __name__ == '__main__':
- main()
处理 scapy 的各种依赖确实恶心, 如果没有经验, 从零开始处理种种依赖包起码半小时, 可以直接用 Kali, Kali 是内置 scapy 的, 能省掉处理依赖包的时间
scapy 是小众工具, Wireshark 是网络流量分析神器, 二者配合, 让计算机网络的研究变容易
以前的 Wireshark 的 Mac 版时经常崩溃, 这次下载了最新版的 Wireshark, 用了 2 天, 没有遇到崩溃的状况, 有兴趣的, 可以试一下
文章涉及到的资源我会通过百度网盘分享, 为便于管理, 资源整合到一张独立的帖子, 链接如下:
http://www.jianshu.com/p/4f28e1ae08b1
来源: http://www.jianshu.com/p/da65f942882d