《Python黑帽子》python3代码实现(第三章)

《Python黑帽子》python3代码实现(第三章)

第三章 网络:原始套接字和流量嗅探

Windows上和Linux上的包嗅探

在示例中,我们首先导入socket与os模块,根据os.name判断主机操作系统,该变量属性当前只注册了三个值,具体如下:

posix

nt

java

Linux

Windows

Java虚拟机

根据操作系统创建原始套接字,这里因为Linux系统只能嗅探到ICMP的数据包,所以这里创建的是基于ICMP包的原始套接字IPPROTO_ICMP,但windows可以嗅探到所有IP数据包IPPROTO_IP,所以这里需要使用os.name对主机操作系统进行判断,然后使用原始套接字构造IP头socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_IP),使用bind()方法对网卡进行监听,这里ICMP包是不具备端口号的,所以端口号为0,然后使用setsockopt()方法设置在捕获的数据包中包含IP头,如果操作系统为windows的话,这里需要使用ioctl()方法开启网卡混杂模式,然后使用recvfrom()方法读取单个数据库,用if语句对操作系统再次判断,如为windows则关闭网卡混杂模式。

import socket

import os

# 监听的网卡 0.0.0.0表示所有网卡

host = "172.16.1.7"

# 创建一个原始套接字(RAW Socket),然后绑定到公开接口上

if os.name == "nt": # Mac的os.name==posix

socket_protocol = socket.IPPROTO_IP

else:

socket_protocol = socket.IPPROTO_ICMP

# Windows和Linux的区别是Windows允许我们嗅探所有协议的所有数据包,但Linux只能嗅探到ICMP数据。

# 使用原始套接字用于构造IP头

sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

sniffer.bind((host, 0)) # 对网卡进行监听,由于ICMP包是不具备端口号的,所以端口填什么都可以,你可以try一try

# 设置在捕获的数据包中包含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头结构:

详情可以参考https://www.cnblogs.com/jacklikedogs/articles/3848263.html

理解完IP头结构之后,我们先直接看看代码:

import socket

import os

import struct

from ctypes import *

# 监听的主机IP

host = "172.16.1.7"

# IP头定义

class IP(Structure):

_fields_ = [

('ihl', c_ubyte, 4), # 头长度ip header 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 linux系统下需要将类型改为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地址

self.src_address = socket.inet_ntoa(struct.pack("

self.dst_address = socket.inet_ntoa(struct.pack("

# 匹配协议类型

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]

# print(raw_buffer[0:20])

# 将缓冲区的前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:

if os.name == 'nt':

sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

示例中添加了对数据包解码,首先定义IP类,使用__new__()方法,当自身实例化时将原始缓冲区中的数据填充到我们刚刚定义的C结构体中,然后使用__init__()方法使数据可视化,最后使用前面示例用到的代码抓取数据包,得到数据包后将前20字节的数据导入结构体中进行初始化,然后输出数据包的信息。

这里__new__()方法和__init__()方法的区别这篇文章就写的非常好:

https://blog.csdn.net/qq_36624456/article/details/98240234

下面是执行代码得到的结果:

解码ICMP

在理解代码之前,我们还是先看看ICMP包的结构:

这里因为各种状态的报文结构不一样,就把目的不可达报文单独拎出来,详细可以看下面这篇文章:

https://www.cnblogs.com/scrat/archive/2012/08/02/2620163.html

接下来贴上代码:

import threading

import socket

import os

import struct

from ctypes import *

import time

from netaddr import IPNetwork, IPAddress

host = "172.16.1.7"

# 目标网段

subnet = "172.16.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("

self.dst_address = socket.inet_ntoa(struct.pack("

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,则进行下一步处理

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)

示例中大部分代码跟之前相同,这里增加了netaddr模块,定义了udp_sender()函数对某个定义的网段发送udp数据包。然后在主函数内开启多线程,再把接受到的所有数据包进行筛选过滤,最后就可以得到存活主机的名单。

下面就是程序运行的结果:

【本章完结】

#

《Python黑帽子》python3代码实现(第三章)相关教程

python黑帽子编程实现没网流量抓包和统计_《Python黑帽子》python3代码实现(第三章)...相关推荐

  1. 《Python黑帽子》python3代码实现(第三章)

    第三章 网络:原始套接字和流量嗅探 Windows上和Linux上的包嗅探 在示例中,我们首先导入socket与os模块,根据os.name判断主机操作系统,该变量属性当前只注册了三个值,具体如下: ...

  2. 基于python的npcap库与dpkt库实现抓包及存储

    基于python的npcap库与dpkt库实现抓包及存储 import pcap import dpkt import socket import sys import getopt import o ...

  3. Python 爬虫,推荐一款简单的抓包工具

    点击上方"AirPython",选择"加为星标" 第一时间关注 Python 原创干货! 1. 前言 传统的抓包工具, 如:Fiddler.Charles.Wi ...

  4. Python 爬虫,推荐一款简单的抓包工具(续)

    点击上方"AirPython",选择"加为星标" 第一时间关注 Python 原创干货! 1. 前言 上篇文章发布之后,有小伙伴后台私信我,说文章只涉及到手机端 ...

  5. python实现系统公网和私网流量监控

    目前很多公司业务已经上云,使用了大量的云主机.当前大多数云厂商的云主机公网都是采用的eip,也就是内网和外网使用的同一张网卡,所以流量全部经过的同一个网卡.然而这就面临一个问题,如何将公网和私网的流量 ...

  6. python能成为编程届的网红么?

    Python本身就是编程语言届的网红,Python,年龄可能比很多读者都要大,但是它在更新快速的编程界却一直表现出色,甚至有人把它比作是编程界的<葵花宝典>,只是Python的速成之法相较 ...

  7. 《Python数据可视化编程实战》—— 1.6 安装图像处理工具:Python图像库(PIL)...

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.6节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  8. python适合自学编程吗-对于0基础的人,直接学 Python 编程合适吗?

    对于0基础的人,直接学 Python 编程合适吗? 我只能说非常合适,因为在目前的编程语言中,Python的抽象程度是最高的,是最接近自然语言的,非常容易上手,Python 可以让你更好的理解编程这件 ...

  9. python抓包代码_Python抓包并解析json爬虫的完整实例代码

    Python抓包并解析json爬虫FwA免费资源网 在使用Python爬虫的时候,通过抓包url,打开url可能会遇见以下类似网址,打开后会出现类似这样的界面,无法继续进行爬虫:FwA免费资源网 Fw ...

  10. Fiddler的下载安装与使用(流量抓包、手机抓包、拦截包、编辑包、重发包)

    Fiddler的下载 打开官网,官网下载地址是https://www.telerik.com/download/fiddler 打开以后选择你的相关信息如下图: 然后点击Download按钮开始下载 ...

最新文章

  1. 1001: 整数求和
  2. SQL Cache Invalidation
  3. Python enumerate函数
  4. Android Binder机制(1501210451 张志康)
  5. SAP Fiori launchpad的PageChipInstance实现
  6. DELPHI串口通讯编程
  7. requests库入门09-OAUTH认证
  8. python设计模式7-桥接模式
  9. 在位运算中_Java常见的运算符(下)
  10. Python实现交通标志牌(GTSRB数据集)解析处理
  11. 基于Java的学生管理系统
  12. IT小知识:文件扩展名小知识大全(A~Z)文件扩展名大全
  13. abb机器人goto指令用法_abb机器人编程指令,机器人编程的程序指令
  14. 用友T1-商贸宝库存商品明细账
  15. 新点软件怎么导入清单_新点造价软件的QDZ招投标清单使用说明
  16. 用计算机画画的图片,如何用画图工具画画
  17. java取0到999整数_Java中输入一个0到999的整数 怎么弄? 谢谢了、
  18. 2021年起重机械指挥考试报名及起重机械指挥考试技巧
  19. VMware虚拟机下载安装详解
  20. 斗鱼房间信息自动化爬取

热门文章

  1. 微信投票刷票器手机免费版、手机微信投票作弊神器原理
  2. 亲测可用|奥维互动地图加载谷歌地图等图源的方法
  3. Python 爬取表情包并保存在数据库中(以往的爬虫改进)
  4. Calico BGP 功能介绍:实现
  5. 《强化学习》-读书笔记-第三章 有限马尔科夫决策过程
  6. 过年了,没买到票的可以过来看一看,12306抢票助手
  7. php怎么发ddos包,解决服务器上通过PHP代码DDOS的方法
  8. 华为OJ 扑克牌大小
  9. 安卓机型刷写第三方twrp 刷写第三方rom的教程和一些问题解决
  10. 有没有测试颜色的软件,用什么软件测试显示器色彩最准:色彩校正软件