python-网络:原始套接字和流量嗅探
来源:互联网 发布:人造暖男网络大电影 编辑:程序博客网 时间:2024/04/29 18:00
一:包嗅探
嗅探工具的主要目标是基于UDP发现目标网络中存活的主机。绝大部分操作系统在处理UDP闭合端口时,存在一种共性行为,可以利用这种特性确定某IP上是否有主机存活,UDP对整个子网发送信息。
当发送一个UDP数据包到主机的某个关闭的UDP端口时,目标主机通常会返回一个ICMP包指示目标端口不可达。这样的ICMP信息意味着目标主机是存活的,如果没有收到UDP数据的任何响应,目标主机应该不存在。
import socketimport os# 监听主机host = "10.21.21.120"# 创建原始套接字,然后绑定在公开接口上if os.name == "nt": socket_protocol = socket.IPPROTO_IPelse: socket_protocol = socket.IPPROTO_ICMPsniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) sniffer.bind((host, 0))# 设置在捕获的数据包中包含IP头sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)# 在WIN平台上,需要设置IOCTL以启用混杂模式if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)# 读取单个数据包print sniffer.recvfrom(65565)# 在WIN平台上关闭混杂模式if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
在win下
在win下使用混淆模式,
混淆模式使得经过这个网卡的所有数据包都会被捕获,
包括那些目标地址不是它的数据包。
linux下
小知识点:
(1)原始套接字直接使用IP协议的套接字,在这个套接字上可以调用connect和bind函数,分别执行绑定对方和本地地址.
(2当需要编写自己的IP数据包首部时,可以在原始套接字上设置套接字选项IP_HDRINCL.在不设置这个选项的情况下,IP协议自动填充IP数据包的首部.
两个比较好的讨论RAW SOCKET的帖子
http://www.cnblogs.com/BeginGame/archive/2011/09/24/2189786.html
http://blog.csdn.net/yanyiyyy/article/details/6566871/
二:解码IP层
嗅探器可以接收任何高层协议如TCP,UDP或ICMP的所有IP头信息,这些信息被打包成二进制数的形式,现在需要解码数据包中IP头的部分,提取协议类型(TCP,UDP,ICMP),源IP地址和目的IP地址等有用信息。
import socketimport osimport structfrom ctypes import *host="10.21.21.120"class IP(Structure): _fields_=[ ("ihl", c_ubyte,4), ("version", c_ubyte,4), ("tos", c_ubyte), ("len", c_ushort), ("id", c_ushort), ("offset", c_ubyte), ("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): self.protocol_map={1:"ICMP",6:"TCP",17:"UDP"} self.src_address=socket.inet_ntoa(struct.pack("<L",self.src)) self.dst_address=socket.inet_ntoa(struct.pack("<L",self.dst)) try: self.protocol=self.protocol_map[self.protocol_num] except: self.protocol=str(self.protocol_num)if os.name=="nt": socket_protocol=socket.IPPROTO_IPelse: socket_protocol=socket.IPPROTO_ICMPsniffer=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol)sniffer.bind((host,0))sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)if os.name=="nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)try: while True: raw_buffer=sniffer.recvfrom(65565)[0] ip_header=IP(raw_buffer[0:20]) print "Protocol:%s %s -> %s" % (ip_header.protocol,ip_header.src_address,ip_header.dst_address)except KeyboardInterrupt: if os.name=="nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
三:解码ICMP
import socketimport osimport structimport threadingfrom ctypes import *host = "10.21.21.120"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("<L",self.src)) self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst)) # human readable protocol try: self.protocol = self.protocol_map[self.protocol_num] except: self.protocol = str(self.protocol_num)class ICMP(Structure): _fields_ = [ ("type", c_ubyte), ("code", c_ubyte), ("checksum", c_ushort), ("unused", c_ushort), ("next_hop_mtu", c_ushort) ] def __new__(self, socket_buffer): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer): pass# create a raw socket and bind it to the public interfaceif os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMPsniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)sniffer.bind((host, 0))# we want the IP headers included in the capturesniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)# if we're on Windows we need to send some ioctls# to setup promiscuous modeif os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)try: while True: # read in a single packet raw_buffer = sniffer.recvfrom(65565)[0] # create an IP header from the first 20 bytes of the buffer ip_header = IP(raw_buffer[0:20]) print "Protocol: %s %s -> %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" % (icmp_header.type, icmp_header.code)# handle CTRL-Cexcept KeyboardInterrupt: # if we're on Windows turn off promiscuous mode if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
四:scanner
import socketimport osimport structimport threadingfrom netaddr import IPNetwork,IPAddressfrom ctypes import *# host to listen onhost = "192.168.238.1"# subnet to targetsubnet = "192.168.238.0/24"# magic we'll check ICMP responses formagic_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,("%s" % ip,65212)) except: passclass 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("<L",self.src)) self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst)) # human readable protocol try: self.protocol = self.protocol_map[self.protocol_num] except: self.protocol = str(self.protocol_num)class ICMP(Structure): _fields_ = [ ("type", c_ubyte), ("code", c_ubyte), ("checksum", c_ushort), ("unused", c_ushort), ("next_hop_mtu", c_ushort) ] def __new__(self, socket_buffer): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer): pass# create a raw socket and bind it to the public interfaceif os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMPsniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)sniffer.bind((host, 0))# we want the IP headers included in the capturesniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)# if we're on Windows we need to send some ioctls# to setup promiscuous modeif os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)# start sending packetst = threading.Thread(target=udp_sender,args=(subnet,magic_message))t.start() try: while True: # read in a single packet raw_buffer = sniffer.recvfrom(65565)[0] # create an IP header from the first 20 bytes of the buffer ip_header = IP(raw_buffer[0:20]) #print "Protocol: %s %s -> %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" % (icmp_header.type, icmp_header.code) # 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: print "Host Up: %s" % ip_header.src_address# handle CTRL-Cexcept KeyboardInterrupt: # if we're on Windows turn off promiscuous mode if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
只扫描出一个ip,网段有问题,ipconfig查看本地连接,无线连接ip,改成如下:
# host to listen onhost = "192.168.1.111"# subnet to targetsubnet = "192.168.1.1/24"
扫描结果
- python-网络:原始套接字和流量嗅探
- 网络编程原始套接字
- 网络编程原始套接字
- Linux网络编程:10. 原始套接字
- 用原始套接字实现网络监听
- 用原始套接字实现网络监听
- 原始套接字实现网络监听
- 网络编程之-原始套接字
- Linux网络编程:原始套接字
- 网络编程之-原始套接字
- Linux网络编程: 原始套接字
- 链路层网络编程技术--原始套接字
- Linux网络编程: 原始套接字
- Linux 网络编程之原始套接字
- Linux 网络编程之原始套接字
- 网络编程(原始套接字)
- 网络编程原始套接字(转)
- Linux 网络编程之原始套接字
- oracle数据库分页查询
- 啊哈!算法—DFS—放扑克
- 内核listen的backlog和简单的三次握手分析
- 141. Linked List Cycle 判断单链表中是否有环
- 《权力与纷争-Shiro》- A Demo
- python-网络:原始套接字和流量嗅探
- RSS2.0规范简易说明
- UIView的autoresizingMask属性的研究
- 系统分层与架构模型
- JAVA经典例题求素数
- 在Java中,如何把一个程序的结果需要保存起来,供下一个程序使用的方式
- hdoj2014(java)青年歌手大奖赛_评委会打分(数组万岁!!!)
- SkyForm CMP(云管理平台)v4.0
- int long等等数据类型的取值范围!!!