Python黑帽子学习笔记-----第三章
来源:互联网 发布:房屋外观设计简单软件 编辑:程序博客网 时间:2024/04/30 03:19
一.Windows和Linux上的包嗅探
首先创建套接字对象,然后再判断程序在哪个平台上运行。在Windows平台上,我们需要通过套接字输入/输出控制(IOCTL)设置一些额外的标志,它允许在网络接口上启用混杂模式。下面例子只设置原始套接字嗅探器,读取一个数据包,然后退出即可
# -*- coding:utf -*-import socketimport os#监听主机#Windows主机IP host = "172.xx.xx.xx"#Linux主机IP#host = "192.168.233.1"# 创建原始套接字,然后绑定在公开接口上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)# 在Windows平台上,我们需要设置IOCTL以启用混杂模式(是用户隔离模式下与内核模式下的组件进行通信的方式)if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)# 读取单个数据包print(sniffer.recvfrom(65565))# 在Windows平台上关闭混杂模式if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
在Windows系统上打开一个管理员模式的cmd窗口,然后运行脚本:
py -2 sniffer.py
二.解码IP层
刚才的代码只是接收了任何高层协议如TCP,UDP或ICMP的所有IP头信息。而且是二进制数的形式,非常难以理解。所以接下来就是解码数据包中IP头的部分,提取诸如协议类型(TCP,UDP和ICMP),源IP地址和目的IP地址等有用信息。下图为典型的IPv4头结构。
IP解码
#!/usr/bin/python #coding=utf-8 import socket import os import struct from ctypes import * #监听的主机--Windows主机 host = "172.xx.xx.x" #IP头定义 class IP(Structure): """docstring for IP""" _fields_ = [ ("ihl", c_ubyte, 4), #ip head length:头长度 ("version", c_ubyte, 4), #版本 ("tos", c_ubyte), #服务类型 ("len", c_ushort), #ip数据包总长度 ("id", c_ushort), #标识符 ("offset", c_ushort), #片偏移 ("ttl", c_ubyte), #生存时间 ("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表 ("sum", c_ushort), #头部校验和 ("src", c_ulong), #源ip地址 ("dst", c_ulong) #目的ip地址 ] 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"} #可读性更强的IP地址 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_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = 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] #将缓冲区的前20个字节按IP头进行解析 ip_header = IP(raw_buffer[0:20]) #输出协议和通信双方IP地址 print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address) #处理CTRL-C except KeyboardInterrupt: #如果运行在Windows上,关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
注:Windows可以看到TCP,UDP,ICMP的数据信息
在Windows系统上打开一个管理员模式的cmd窗口,然后运行脚本:
py -2 sniffer_ip_header_decode.py程序运行后的效果截图
程序运行在Linux下时需要将_fields_中的src和dst修改一下,变化如下:
_fields_ = [ ("ihl", c_ubyte, 4), #ip head length:头长度 ("version", c_ubyte, 4), #版本 ("tos", c_ubyte), #服务类型 ("len", c_ushort), #ip数据包总长度 ("id", c_ushort), #标识符 ("offset", c_ushort), #片偏移 ("ttl", c_ubyte), #生存时间 ("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表 ("sum", c_ushort), #头部校验和 ("src", c_ulong), #源ip地址 Windows版 ("dst", c_ulong) #目的ip地址 Windows 版 ]
修改后:
_fields_ = [ ("ihl", c_ubyte, 4), #ip head length:头长度 ("version", c_ubyte, 4), #版本 ("tos", c_ubyte), #服务类型 ("len", c_ushort), #ip数据包总长度 ("id", c_ushort), #标识符 ("offset", c_ushort), #片偏移 ("ttl", c_ubyte), #生存时间 ("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表 ("sum", c_ushort), #头部校验和 ("src", c_uint32), #源ip地址 ("dst", c_uint32) #目的ip地址 ]http://blog.csdn.net/hugo2052/article/details/78277065
Linux系统下的运行效果如下:
正在ping www.baidu.com 获得的数据包
三.解码ICMP
ICMP每条信息都包含三个固定的字段:数据类型,代码值和校验和。数据类型和代码值字段包含了主机接收到的ICMP信息的类别,它们揭示了正确解码ICMP信息的方法。
sniffer_with_icmp.py
#!/usr/bin/python #coding=utf-8 import socket import os import struct from ctypes import * #监听的主机 #host = "192.168.64.128" #Windows主机地址#host = "172.xx.xx.xx" # 实训iphost = "10.0.x.x"#IP头定义 class IP(Structure): """docstring for IP""" _fields_ = [ ("ihl", c_ubyte, 4), #ip head length:头长度 ("version", c_ubyte, 4), #版本 ("tos", c_ubyte), #服务类型 ("len", c_ushort), #ip数据包总长度 ("id", c_ushort), #标识符 ("offset", c_ushort), #片偏移 ("ttl", c_ubyte), #生存时间 ("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表 ("sum", c_ushort), #头部校验和 ("src", c_uint32), #源ip地址 ("dst", c_uint32) #目的ip地址 ] 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"} #可读性更强的IP地址 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) #------------ICMP add----------------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 #----------------------------- #下面的代码类似于之前的例子 if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) #这里端口为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] #将缓冲区的前20个字节按IP头进行解析 ip_header = IP(raw_buffer[0:20]) #输出协议和通信双方IP地址 print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address) # ------------------ICMP add------------------ # 如果为ICMP,进行处理 if ip_header.protocol == "ICMP": # 计算ICMP包的起始位置 offset = ip_header.ihl * 4 buf = raw_buffer[offset:offset + sizeof(ICMP)] #解释ICMP数据 icmp_header = ICMP(buf) print("ICMP -> Type:%d Code: %d " % (icmp_header.type,icmp_header.code)) # ------------------------------------#处理CTRL-C except KeyboardInterrupt: #如果运行在Windows上,关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
Windows下运行效果:
4.小试牛刀
使用扫描器对局域网进行扫描寻找其他主机
首先要先安装netaddr
easy_install netaddr
#-*- coding:utf8 -*- import socket import os import struct import threading import time import sys from netaddr import IPNetwork,IPAddress from ctypes import * # 监听主机,即监听那个网络接口,下面的ip为我的ip #host = "172.xx.xx.xx" # 实训iphost = "10.0.2.10" # 扫描的目标子网 # subnet = "192.168.1.0/24" # 没有命令行参数,默认192.168.1.0/24 if len(sys.argv) == 1:# 扫描当前IP网段存在的主机 #subnet = "172.19.65.0/24" subnet = "10.0.2.0/24"else: subnet = sys.argv[1] # 自定义的字符串,我们将在ICMP响应中进行核对 magic_message = "PYTHONRULES!" # 批量发送UDP数据包 def udp_sender(subnet, magic_message): time.sleep(5) #可以说程序暂停5秒吧 # 建立一个socket对象(SOCK_DGRAM:UDP客户端) sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for ip in IPNetwork(subnet): try: # 尝试发送magic_message这个消息到子网的每个ip,还用了个不怎么可能用的65212端口 sender.sendto(magic_message, ("%s" % ip, 65212)) except: pass #代表什么也不做 # ip头定义 class IP(Structure): _fields_ = [ ("ihl", c_ubyte, 4), #ip head length:头长度 ("version", c_ubyte, 4), #版本 ("tos", c_ubyte), #服务类型 ("len", c_ushort), #ip数据包总长度 ("id", c_ushort), #标识符 ("offset", c_ushort), #片偏移 ("ttl", c_ubyte), #生存时间 ("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表 ("sum", c_ushort), #头部校验和 ("src", c_uint32), #源ip地址 ("dst", c_uint32) #目的ip地址 ] # __new__(cls, *args, **kwargs) 创建对象时调用,返回当前对象的一个实例;注意:这里的第一个参数是cls即class本身 def __new__(self, socket_buffer=None): return self.from_buffer_copy(socket_buffer) # __init__(self, *args, **kwargs) 创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用__new__之后,根据返回的实例初始化;注意,这里的第一个参数是self即对象本身【注意和new的区别】 def __init__(self, socket_buffer=None): # 协议字段与协议名称的对应 self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"} # 可读性更强的ip地址(转换32位打包的IPV4地址为IP地址的标准点号分隔字符串表示。) 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) class ICMP(Structure): # _fields_ = [ ("type", c_ubyte), #类型 ("code", c_ubyte), #代码值 ("checksum", c_ubyte), #头部校验和 ("unused", c_ubyte), #未使用 ("next_hop_mtu", c_ubyte) #下一跳的MTU ] def __new__(self, socket_buffer): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer): pass if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) #raw的中文是生的意思,大概就是原始套接字的意思吧 sniffer.bind((host, 0)) #这里端口为0,监听所有端口吧~ # 设置在捕获的数据包中包含IP头 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # 在Windows平台上,我们需要设置IOCTL以启用混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) # 开启多线程发送udp数据包 t = threading.Thread(target=udp_sender, args=(subnet, magic_message)) t.start() try: while True: # 读取数据包 raw_buffer = sniffer.recvfrom(65565)[0] # 将缓冲区的前20个字节按IP头进行解析 ip_header = IP(raw_buffer[0:20]) # 输出协议和通信双方IP地址 #print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address) # 如果为ICMP,进行处理 if ip_header.protocol == "ICMP": # 计算ICMP包的起始位置,并获取ICMP包的数据 offset = ip_header.ihl * 4 #ihl是头部长度,代表32位(即4字节)长的分片的个数 [我的理解是因为一个字节表示一个符号,所以这里的offset要搞成以字节为单位的,为的是下一句的提取数据] buf = raw_buffer[offset:offset+sizeof(ICMP)] # 解析ICMP数据 icmp_header = ICMP(buf) #print "ICMP -> Type: %d Code: %d" % (icmp_header.type, icmp_header.code) # 检查类型和代码值是否都为3 if icmp_header.type == 3 and icmp_header.code == 3: # 确认响应的主机再我们的目标子网之内 if IPAddress(ip_header.src_address) in IPNetwork(subnet): # 确认ICMP包中包含我们发送的自定义的字符串 if raw_buffer[len(raw_buffer) - len(magic_message):] == magic_message: print "Host Up: %s" % ip_header.src_address # 处理CTRL-C except KeyboardInterrupt: # 如果运行再Windows上,关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
由于我的网段只有本机所以只能扫描自己的ip
阅读全文
0 0
- Python黑帽子学习笔记-----第三章
- Python黑帽子学习笔记-----第二章
- 《Python黑帽子》学习笔记
- Python黑帽子开篇
- 关于《Python黑帽子:黑客与渗透测试编程之道》的学习笔记
- python黑帽子 pydasm 配置
- 读书笔记 -《Python 黑帽子》 ( 一 )
- 读书笔记 -《Python 黑帽子》 ( 三 )
- 读书笔记 -《Python 黑帽子》 ( 二 )
- 读书笔记 -《Python 黑帽子》 ( 四 )
- 读书笔记 -《Python 黑帽子》 ( 五 )
- Python黑帽子:取代netcat
- 《python 黑帽子》 示例 :TCP客户端
- 《python 黑帽子》 示例 :UDP客户端
- Python 黑帽子 snffer ip header decoder
- python黑帽子之netcat(chapter1)
- 《Python黑帽子 黑客与渗透测试编程之道》的学习(一)
- python学习笔记 第三章
- Windows 下 Apache2 Django配置(针对找不到mod_wsgi.so)
- NetDataUtil_获取网络数据的工具类
- 浅论3大方法求单源最短路以及2大方法求最小生成树
- 记忆网络之Hierarchical Memory Networks(架构分层)
- U盘启动盘恢复原来的大小
- Python黑帽子学习笔记-----第三章
- win7系统在启动MySQL Query Browser时出现的Error2003错误及解决办法
- p59 第一题
- linux常见网络设置
- NetWorkUtil_使用网络状态的判断
- webpack安装和命令行
- windows nginx 80端口占用
- 回溯法解决八人过河问题
- 洗礼灵魂,修炼python(1)--python简介