python黑帽子(第三章)
Windows/Linux下包的嗅探
根据os.name判断操作系统 下面是os的源码
posix是Linux nt是Windows
在windows中需要管理员权限、linux中需要root权限 因为是开启混杂模式(混杂模式允许我们嗅探网卡上流经的所有数据包,即使数据的目的地址不是本机)
import socket
import os # 监听的网卡 0.0.0.0表示所有网卡
host = "192.168.1.102" # Windows和Linux的区别是Windows允许我们嗅探所有协议的所有数据包,但Linux只能嗅探到ICMP数据。
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP # 用于接收任何ip包
else:
socket_protocol = socket.IPPROTO_ICMP # 只接受icmp # SOCK_RAW是一种底层的SOCKET编程接口 可以处理ICMP、IGMP等网络报文、可以处理一些特殊协议报文以及操作IP层及其以上的数据
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) sniffer.bind((host, 21)) # 对网卡进行监听端口无所谓 # 设置在捕获的数据包中包含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(65535)) # 在Windows平台上关闭混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
解码IP头
上面只是捕获了包含ip头的数据包,现在我们来解码关于ip头的信息
ipv4头结构 每行32位
import socket
import os
import struct
from ctypes import *
# 监听的主机IP
host = "192.168.1.102"
# IP头定义
class IP(Structure):
_fields_ = [
('ihl', c_ubyte, 4), # 头长度
('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 linux需要将c_ulong改为c_uint32
('dst', c_ulong) # 目的IP
]
def __new__(cls, socket_buffer=None): # new()方法是在类准备将自身实例化时调用,将原始缓冲区中的数据填充到结构中
return cls.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer=None):
# 协议字段与协议名称对应
self.protocol_map = {1: 'ICMP', 6: 'TCP', 17: 'UDP'}
# 可读性更强的IP地址,struct.pack()将数据解码为"<"小端,"L"无符号长型
# inet_ntoa() 将32bit数值转换为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 = 0
else:
socket_protocol = 1
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个字节也就是前160位为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:
if os.name == 'nt':
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
解码icmp
当发送一个UDP数据包到主机的某个关闭的UDP端口上时,目标主机通常会返回一个ICMP包指示目标端口不可达。这样的ICMP信息意味着目标主机是存活的,因为我们可以假设如果没有接受到发送的UDP数据的任何响应,目标主机应该不存在。
import threading
import socket
import os
import struct
from ctypes import *
import time
from netaddr import IPNetwork, IPAddress
host = "192.168.1.102"
# 目标网段
subnet = "192.168.1.0/24"
# 自定义字段,用于辨别收到的包是否是响应我们的UDP请求
magic_message = b'PYTHONRULES!'
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__(cls, socket_buffer=None):
return cls.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)
# ICMP包头定义
class ICMP(Structure):
_fields_ = [
("type", c_ubyte), # 类型
("code", c_ubyte), # 代码值
("checksum", c_ushort), # 头部校验和
("unused", c_ushort), # 未使用
("next_hop_mtu", c_ushort) # 下一跳的MTU
]
def __new__(cls, socket_buffer=None):
return cls.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer=None):
pass
# 批量发送UDP请求包
def udp_sender(subnet, magic_message):
time.sleep(2)
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for ip in IPNetwork(subnet):
try:
# 设置端口为大于1023的端口号,尽量使用不常用端口
sender.sendto(magic_message, (str(ip), 65212))
except:
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))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
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(65535)[0]
ip_header = IP(raw_buffer[0:20])
# print("protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address))
# 如果协议为ICMP,则进行下一步处理 ip协议的
if ip_header.protocol == 'ICMP':
# 计算真实IP头长度 --> 计算公式:ihl(4位二进制换算十进制) * 4 = ip头长度(字节)
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))
# 收到检查类型为3,代码为3的ICMP包则说明目标主机存在
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)
except KeyboardInterrupt:
if os.name == 'nt':
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
python黑帽子(第三章)的更多相关文章
- python黑帽子(第五章)
对开源CMS进行扫描 import os import queue import requests # 原书编写时间过于久远 现在有requests库对已经对原来的库进行封装 更容易调用 import ...
- python黑帽子(第四章)
Scapy窃取ftp登录账号密码 sniff函数的参数 filter 过滤规则,默认是嗅探所有数据包,具体过滤规则与wireshark相同. iface 参数设置嗅探器索要嗅探的网卡,默认对所有的网卡 ...
- 读书笔记 ~ Python黑帽子 黑客与渗透测试编程之道
Python黑帽子 黑客与渗透测试编程之道 <<< 持续更新中>>> 第一章: 设置python 环境 1.python软件包管理工具安装 root@star ...
- 2017-2018-2 20179204 PYTHON黑帽子 黑客与渗透测试编程之道
python代码见码云:20179204_gege 参考博客Python黑帽子--黑客与渗透测试编程之道.关于<Python黑帽子:黑客与渗透测试编程之道>的学习笔记 第2章 网络基础 t ...
- python学习心得第三章
python学习心得第三章 1.三元运算 变量=值1 if 条件 else 值2 由图如果条件成立则赋值1给变量,如果条件不成立则赋值2给变量. 2.数据类型 集合:set() class set(o ...
- python学习笔记——第三章 串
第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...
- 《零压力学Python》 之 第三章知识点归纳
第三章(第一个程序)知识点归纳 编程犹如写剧本.Python函数与剧本差别不大,你可以反复调用函数,而它每次都执行预定的“脚本”(脚本也可以指整个程序). 在Python IDLE中,真正的编程是从编 ...
- 跟着高淇学Python——第一到第三章总结
2019/10/26 第一章:Python介绍 Python是一种解释型,面向对象的语言.特点是: 可读性强 简洁,简洁 面向对象 免费开源 可移植性和跨平台性 丰富的库 可扩展性 应用范围:1.人工 ...
- 路飞学城-Python爬虫集训-第三章
这个爬虫集训课第三章的作业讲得是Scrapy 课程主要是使用Scrapy + Redis实现分布式爬虫 惯例贴一下作业: Python爬虫可以使用Requests库来进行简单爬虫的编写,但是Reque ...
随机推荐
- Redis的Unable to connect to Redis和java.io.IOException: 远程主机强迫关闭了一个现有的连接问题的解决
学习项目xhr系统用到springboot + vue(https://github.com/lenve/vhr),文档中要求使用到RabbitMQ,但是从我搭建开发环境来看,是否配置Rabbit ...
- vue学习过程总结(06) - vue的数据存储store
这个不知道能怎么叫不?现在对这块很迷.以下为个人理解 store是状态管理,是一个对象,有其属性和方法. 常见的值有:state/mutations/actions/getters, 这几个值的意思: ...
- python练习册 每天一个小程序 第0013题
# -*-coding:utf-8-*- ''' 题目描述: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-) 地址: http://tieba.baidu.com/p/21 ...
- 【推理引擎】ONNX 模型解析
定义模型结构 首先使用 PyTorch 定义一个简单的网络模型: class ConvBnReluBlock(nn.Module): def __init__(self) -> None: su ...
- ubuntu16.04启动ssh服务
1 查看ssh服务是否开启 ps -e | grep ssh* 2如果没有则安装ssh apt-get install openssh-server openssh-client 3再看服务就有ssh ...
- 什么是线程池(thread pool)?
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内 存资源或者其它更多资源.在 Java 中更是如此,虚拟机将试图跟踪每一个对象, 以便能够在对象销毁后进行垃圾回收.所以提高服务程 ...
- Windows10安装PHP7+Apache 2.4
下载下面的文件 httpd-2.4.39-win64-VC15.zip php-7.3.4-Win32-VC15-x64.zip 如果下载失效,从这里下载 https://windows.php.ne ...
- (stm32f103学习总结)—GPIO结构
一.GPIO基本结构 二.GPIO工作模式 输入模式 输入浮空 输入上拉 输入下拉 模拟输入 输出模式 开漏输出 开漏复用功能 推挽式输出 推挽式复用功能 库函数中所对应的代码 1 typedef e ...
- 该如何选择 background-image 和 img 标签
用img标签 如果你希望别人打印页面时候包含这张图片请使用 img 标签 当这张图片有非常有意义的语义,比如警告图标,请使用img标签及它的alt属性.这样意味着你可以向所有的用户终端现实他的意义. ...
- Javascript Symbol 隐匿的未来之星
ES6中基础类型增加到了7种,比上一个版本多了一个Symbol,貌似出现了很长时间,但却因没有使用场景,一直当作一个概念层来理解它,我想,用它的最好的方式,还是要主动的去深入了解它吧,所以我从基础部分 ...