7-IP地址段存活主机扫描
思路:
1、定义一个简单的字符串作为签名,用于确认收到的ICMP响应是否是我们发送的UDP包触发的;
2、udp_sender函数会读取程序开头定义的子网,往这个子网的每一个地址发送UDP数据包;
3、定义一个名为scanner的类,初始化这个类时,需要传递扫描器所在的主机IP,即程序运行的位置;
初始化过程中,创建一个socket对象(windows上需要启动网络混杂模式),并把这个对象设定为scanner类的成员变量;
4、sniff函数会嗅探网络上的数据,并把在线的主机记录下来:
接收到ICMP消息时,首先检查是不是来自我们正在扫描的子网,然后检查ICMP消息里有没有我们自定义的签名;
如果所有检查都通过了,就把这条主机IP信息打印出来,使用ctrl+c组合键中断扫描,程序会关闭网卡混杂模式,并把扫描出来的主机打印出来,然后退出程序;
IP报头格式: ICMP报头格式:
ICMP 报文分类:
Type |
Code |
描述 |
查询/差错 |
---|---|---|---|
0-Echo响应 |
0 |
Echo响应报文 |
查询 |
3-目的不可达 |
0 |
目标网络不可达报文 |
差错 |
1 |
目标主机不可达报文 |
差错 |
|
2 |
目标协议不可达报文 |
差错 |
|
3 |
目标端口不可达报文 |
差错 |
|
4 |
要求分段并设置DF flag标志报文 |
差错 |
|
5 |
源路由失败报文 |
差错 |
|
6 |
未知的目标网络报文 |
差错 |
|
7 |
未知的目标主机报文 |
差错 |
|
8 |
源主机隔离报文 |
差错 |
|
9 |
禁止访问的网络报文 |
差错 |
|
10 |
禁止访问的主机报文 |
差错 |
|
11 |
对特定的TOS网络不可达报文 |
差错 |
|
12 |
对特定的TOS主机不可达报文 |
差错 |
|
13 |
由于过滤 网络流量被禁止报文 |
差错 |
|
14 |
主机越权报文 |
差错 |
|
15 |
优先权终止生效报文 |
差错 |
|
5-重定向 |
0 |
重定向网络报文 |
差错 |
1 |
重定向主机报文 |
差错 |
|
2 |
基于TOS的网络重定向报文 |
差错 |
|
3 |
基于TOS的主机重定向报文 |
差错 |
|
8-Echo请求 |
0 |
Echo请求报文 |
查询 |
9-路由器通告 |
0 |
路由通告报文 |
查询 |
10-路由器请求 |
0 |
路由器的发现/选择/请求报文 |
查询 |
11-ICMP超时 |
0 |
TTL超时报文 |
差错 |
1 |
分片重组超时报文 |
差错 |
|
12-参数问题 |
0 |
IP报首部参数错误报文 |
差错 |
1 |
丢失必要选项报文 |
差错 |
|
2 |
不支持的长度报文 |
差错 |
|
13-时间戳请求 |
0 |
时间戳请求报文 |
查询 |
14-时间戳应答 |
0 |
时间戳应答报文 |
查询 |
15-信息请求 |
0 |
信息请求报文 |
查询 |
16-信息应答 |
0 |
信息应答报文 |
查询 |
scanner.py
# -*-utf-8-*-
import ipaddress
import struct
import socket
import os
import sys
import time
import threading
SUBNET = input('subnet(1.1.1.0/24): ')
MSG = 'PYTHONRULES'
# 使用struct库定义一个IP类
class IP:
def __init__(self, buffer = None):
header = struct.unpack('!BBHHHBBH4s4s', buffer)
self.version = header[0] >> 4
self.header_len = header[0] & 0xF
self.tos = header[1]
self.total_len = header[2]
self.id = header[3]
self.frag_off = header[4]
self.ttl = header[5]
self.protocol = header[6]
self.check = header[7]
self.src = header[8]
self.dst = header[9]
self.src_addr = ipaddress.ip_address(self.src)
self.dst_addr = ipaddress.ip_address(self.dst)
self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
try:
self.protocol = self.protocol_map[self.protocol]
except Exception as e:
print(f'{e} No protocol for {self.protocol}')
self.protocol = str(self.protocol)
class ICMP:
def __init__(self, buffer):
header = struct.unpack('!BBHHH', buffer)
self.type = header[0]
self.code = header[1]
self.checksum = header[2]
self.unused = header[3]
self.next_hop_mtu = header[4]
# udp datagrames with magic message
def udp_sender():
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
for ip in ipaddress.ip_network(SUBNET).hosts():
s.sendto(bytes(MSG,'utf-8'), (str(ip), 65212))
class scanner:
def __init__(self, host):
self.host = host
if os.name == 'nt':
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
self.scoket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
self.scoket.bind((host, 0))
self.scoket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if os.name == 'nt':
self.scoket.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) #开启混杂模式
def sniff(self):
hosts_up = set([f'{str(self.host)} *'])
try:
while True:
raw_buffer = self.scoket.recvfrom(65565)[0]
ip_header = IP(raw_buffer[0:20])
if ip_header.protocol == 'ICMP':
offset = ip_header.header_len * 4
buf = raw_buffer[offset:offset + 8]
icmp_header = ICMP(buf)
if icmp_header.type == 3 and icmp_header.code == 3:
if ipaddress.ip_address(ip_header.src) in hosts_up:
if raw_buffer[len(raw_buffer) - len(MSG):] == bytes(MSG,'utf-8'):
tgt = str(ip_header.src_addr)
if tgt != self.host and tgt not in hosts_up:
hosts_up.add(tgt)
print(f'[+] {tgt} is UP')
except KeyboardInterrupt:
if os.name == 'nt':
self.scoket.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) #关闭混杂模式
print('\nuser interrupted')
if hosts_up:
print(f'{len(hosts_up)} UP hosts')
for host in sorted(hosts_up):
print(f'{host}')
print('\n')
sys.exit(0)
if __name__ == '__main__':
if len(sys.argv) == 2:
host = sys.argv[1]
else:
host = '192.168.1.101'
s = scanner(host)
time.sleep(5)
t = threading.Thread(target=udp_sender)
t.start()
s.sniff()
ctrl+c中断扫描后如下:
本文来自博客园,作者:段愿仁长九,转载请注明原文链接:https://www.cnblogs.com/gaogaoing/p/17691838.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架