一、开发环境
windows7 32位,python3.7
二,安装netaddr模块
netaddr模块能方便的对子网和IP地址进行操作。
三,工作原理
通过构建套接字对象对网络接口上的数据包嗅探,windows与linux的区别是windows允许我们嗅探所有协议的所有数据包,而linux只能嗅探到ICMP数据。当我们发送UDP数据到活动主机关闭的端口上时,会产生ICMP响应,ICMP响应的数据属性中,有一个类型值(type)和代码值(code),当这两个值都为3时,代表主机端口不可达。
四,代码
import socket
import os
import struct
import threading
from netaddr import IPNetwork,IPAddress
from ctypes import *
# host to listen on
host = "192.168.0.149"
# subnet to target
subnet = "192.168.0.0/24"
# magic we'll check ICMP responses for
magic_message = "PYTHONRULES!"
def udp_sender(subnet,magic_message):
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for ip in IPNetwork(subnet):
try:
sender.sendto(magic_message.encode(),("%s" % ip,65212))
except Exception as e:
raise(e)
class IP(Structure):
_fields_ = [
("ihl", c_ubyte, 4),
("version", c_ubyte, 4),
("tos", c_ubyte),
("len", c_ushort),
("id", c_ushort),
("offset", c_ushort),
("ttl", c_ubyte),
("protocol_num", c_ubyte),
("sum", c_ushort),
("src", c_ulong),
("dst", c_ulong)
]
def __new__(self, socket_buffer=None):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer=None):
# map protocol constants to their names
self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}
# human readable IP addresses
self.src_address = socket.inet_ntoa(struct.pack(" %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)
# if it's ICMP we want it
if ip_header.protocol == "ICMP":
# calculate where our ICMP packet starts
offset = ip_header.ihl * 4
buf = raw_buffer[offset:offset + sizeof(ICMP)]
# create our ICMP structure
icmp_header = ICMP(buf)
#print("ICMP -> Type: %d Code: %d ip:%s" % (icmp_header.type, icmp_header.code,ip_header.src_address))
# now check for the TYPE 3 and CODE 3 which indicates
# a host is up but no port available to talk to
if icmp_header.code == 3 and icmp_header.type == 3:
# check to make sure we are receiving the response
# that lands in our subnet
if IPAddress(ip_header.src_address) in IPNetwork(subnet):
# test for our magic message
if raw_buffer[len(raw_buffer)-len(magic_message):] == magic_message.encode():
print("Host Up: %s" % ip_header.src_address)
# handle CTRL-C
except KeyboardInterrupt:
# if we're on Windows turn off promiscuous mode
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
上面代码出自《Black Hat Python》,但我是在win7 32的python3上运行的,代码稍微有点改动。运行结果如下“