读书笔记 -《Python 黑帽子》 ( 二 )

2023-11-16

读书笔记系列文章

一直都在读书,读了忘,忘了再读。不如把每次学到的东西都写下来

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

我的工作内容就是用C 语言写嗅探工具和 DPI。基本的工作原理和本章的内容是非常相似的。所以理解起来会比较容易一些。arp 欺骗和中间人攻击也玩过,所以对这些知识并不陌生。玩的时候用的也是别人的工具,arp 欺骗用的 dsniff 中的 arpspoof,中间人攻击用的 sslsplit,有空也把这些写下来。继续读书

这一章通过原始套接字来解析 IP 协议和 ICMP 协议的信息

开发 UDP 主机发现工具

这一节解释了利用 UDP 协议发现目标网络中的存活主机,其实用 nmap 工具就能实现,但毕竟这本书毕竟是教我们怎么开发自己的工具的,所以还是多懂一些原理比较好。基本原理可以概括为使用 UDP 向目标网络中所有 IP 地址的特定端口发送数据,如果 up 的主机收到这样的报文并且该端口是关闭的,那么就会返回一个 ICMP 报文,表示目标不可达。如果我们发送 UDP 报文后,接着抓到这些 ICMP 报文,那么就能确定哪些主机是 UP 状态了。

Windows 和 Linux 上的包嗅探

混杂模式就不用多介绍了,要想抓包,总是要打开网卡的混杂模式,抓取网卡上流经的所有的包。不过是 Windows还是 Linux 都是需要管理员权限打开。
这一节讲了一个有趣的事情,Windows 允许我们嗅探所有协议的所有数据包,但是 Linux 只能修改 ICMP 数据。
看一段这一节用到的代码吧。很简单,直接读注释就好了。

import socket
import os

# host to listen on
host = "192.168.0.196"

# create a raw socket and bind it to the public interface
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))

# we want the IP headers included in the capture
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# if we're on Windows we need to send an IOCTL
# to setup promiscuous mode
if os.name == "nt": 
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# read in a single packet
print sniffer.recvfrom(65565)

# if we're on Windows turn off promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

解析 IP 层

一直是使用 C 语言来解析 IP 包的,C 语言处理这种数据其实更有优势,指针和数据类型更好使。作者使用 python 的 Ctype 来定义结构体,来完成一些 python 自身不好完成的东西。这也是 python 和 c 天生的血液相连啊。

这一节的代码还是比较简单的,看注释基本就能看懂,看不懂的地方估计就是 Ctype 的使用方法了,python 可读性这么好,还是比较好理解它背后的意思。

但是这个代码是有点问题的。作者使用的 kali 是32位的,我的是64位的,所以在使用 Ctype 的时候,c_ushort和 c_ulong的长度可能会和我的不一样。在我这里运行的时候,代码出错了。于是我把 c_ushort修改为 c_uint16,把 c_ulong修改为 c_uint32,这样就没有问题了。

import socket
import os
import struct
from ctypes import *

# host to listen on
host   = "192.168.0.187"

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)

# create a raw socket and bind it to the public interface
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))

# we want the IP headers included in the capture
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# if we're on Windows we need to send some ioctls
# to setup promiscuous mode
if 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)

except KeyboardInterrupt:
    # if we're on Windows turn off promiscuous mode
    if os.name == "nt":
        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

解码 ICMP

这一节的内容和上节的编写代码的方式是一样的,定义结构体解析 ICMP 的数据。ICMP 报文有两个比较关键的字段,分别是类型值和代码值。在『UDP 主机发现工具』这一节里面,说明了,要想嗅探存活的主机,需要截获返回的 ICMP 报文,目标不可达时,这两个值都是3,同时这个 ICMP 报文的最后8个字节指出了源 UDP 报文的ip 头的8个字节。所以分析返回的 ICMP 报文时,只需要判断这两个值就能判断主机是否存活了。

最后了,完成这个嗅探器

通过以上两节的内容,基本就可以确定嗅探器是怎么实现的了。
只需要开两个线程,一个发送 udp 报文给目标网路的特定端口;另一个线程抓去返回的 ICMP 包就可以了,捉到了哪一个,哪一个就是 UP 状态的。

这一节的代码也是比较好理解的,看代码注释就好了,这里面有一个比较好玩的第三方包 netaddr。这个包可以将「192.168.0.1/24」解析为192.168.0.1 ~ 192.168.0.255 这样的数组。

import socket
import os
import struct
import threading

from netaddr import IPNetwork,IPAddress
from ctypes import *

# host to listen on
host   = "192.168.0.187"

# 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,("%s" % ip,65212))
        except:
            pass


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 interface
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))

# we want the IP headers included in the capture
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# if we're on Windows we need to send some ioctls
# to setup promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)


# start sending packets
t = 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-C
except KeyboardInterrupt:
    # if we're on Windows turn off promiscuous mode
    if os.name == "nt":
        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读书笔记 -《Python 黑帽子》 ( 二 ) 的相关文章

  • 如何恢复tensorflow inceptions检查点文件(ckpt)?

    I have inception resnet v2 2016 08 30 ckpt文件是预先训练的初始模型 我想使用恢复这个模型 saver restore sess ckpt filename 但为此 我将需要编写训练该模型时使用的变量
  • 在 Python 中解析 TCL 列表

    我需要在双括号上拆分以空格分隔的 TCL 列表 例如 OUTPUT 172 25 50 10 01 01 Ethernet 172 25 50 10 01 02 Ethernet Traffic Item 1 172 25 50 10 01
  • 如何计算 pandas datetime 对象的均值和方差?

    如何计算 YYYY MM DD 形式的 python 日期时间对象的汇总统计数据 均值和标准差 我想对具有不同 ID 的不同日期时间对象组执行此操作 数据如下 import datetime as dt df pd DataFrame Da
  • 使用 MongoDB 作为我们的主数据库,我应该使用单独的图数据库来实现实体之间的关系吗?

    我们目前正在为一家专业公司内部实施类似 CRM 的解决方案 由于存储信息的性质以及信息的不同值和键 我们决定使用文档存储数据库 因为它完全适合目的 在本例中我们选择 MongoDB 作为此 CRM 解决方案的一部分 我们希望存储实体之间的关
  • Python - 比较同一字典中的值

    我有一本字典 d Trump MAGA FollowTheMoney Clinton dems Clinton Stein FollowTheMoney Atlanta 我想删除字符串列表中的重复字符串 该字符串是键的值 对于这个例子 期望
  • 计算另一个字符串中多个字符串的出现次数

    在 Python 2 7 中 给定以下字符串 Spot是一只棕色的狗 斑点有棕色的头发 斑点的头发是棕色的 查找字符串中 Spot brown 和 hair 总数的最佳方法是什么 在示例中 它将返回 8 我正在寻找类似的东西string c
  • matplotlib 图中点的标签

    所以这是一个关于已发布的解决方案的问题 我试图在我拥有的 matplotlib 散点图中的点上放置一些数据标签 我试图在这里模仿解决方案 是否有与 MATLAB 的 datacursormode 等效的 matplotlib https s
  • VSCode Settings.json 丢失

    我正在遵循教程 并尝试将 vscode 指向我为 Scrapy 设置的虚拟工作区 但是当我在 VSCode 中打开设置时 工作区设置 选项卡不在 用户设置 选项卡旁边 我还尝试通过以下方式手动转到文件 APPDATA Code User s
  • 在 Django Admin 中调整字段大小

    在管理上添加或编辑条目时 Django 倾向于填充水平空间 但在某些情况下 当编辑 8 个字符宽的日期字段或 6 或 8 个字符的 CharField 时 这确实是一种空间浪费 字符宽 然后编辑框最多可容纳 15 或 20 个字符 我如何告
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 打印包含字符串和其他 2 个变量的变量

    var a 8 var b 3 var c hello my name is var a and var b bye print var c 当我运行程序时 var c 会像这样打印出来 hello my name is 8 and 3 b
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 未知错误:Chrome 无法启动:异常退出

    当我使用 chromedriver 对 Selenium 运行测试时 出现此错误 selenium common exceptions WebDriverException Message unknown error Chrome fail
  • Django 视图中的“请求”是什么

    在 Django 第一个应用程序的 Django 教程中 我们有 from django http import HttpResponse def index request return HttpResponse Hello world
  • 如何将 GAE 中一种 Kind 中的所有实体复制到另一种 Kind 中,而无需显式调用每个属性

    我们如何使用function clone entity 如中所述在 Python 中复制 Google App Engine 数据存储中的实体 而无需在 编译 时知道属性名称 https stackoverflow com question
  • 如何使用 Python 3 检查目录是否包含文件

    我到处寻找这个答案但找不到 我正在尝试编写一个脚本来搜索特定的子文件夹 然后检查它是否包含任何文件 如果包含 则写出该文件夹的路径 我已经弄清楚了子文件夹搜索部分 但检查文件却难倒了我 我发现了有关如何检查文件夹是否为空的多个建议 并且我尝
  • 每当使用 import cv2 时 OpenCV 都会出错

    我在终端上使用 pip3 install opencv contrib python 安装了 cv2 并且它工作了 但是每当我尝试导入 cv2 或运行导入了 cv2 的 vscode 文件时 在 python IDLE 上它都会说 Trac
  • pandas.read_csv 将列名移动一倍

    我正在使用位于的 ALL zip 文件here http www fec gov disclosurep PDownload do 我的目标是用它创建一个 pandas DataFrame 但是 如果我跑 data pd read csv
  • 如何在 Flask 中的视图函数/会话之间传递复杂对象

    我正在编写一个 Web 应用程序 当 且仅当 用户登录时 该应用程序从第三方服务器接收大量数据 这些数据被解析为自定义对象并存储在list 现在 用户在应用程序中使用这些数据 调用不同的视图 例如发送不同的请求 我不确定什么是最好的模式在视
  • 如何将Python3设置为Mac上的默认Python版本?

    有没有办法将 Python 3 8 3 设置为 macOS Catalina 版本 10 15 2 上的默认 Python 版本 我已经完成的步骤 看看它安装在哪里 ls l usr local bin python 我得到的输出是这样的

随机推荐

  • 可重入锁简单理解

    可重入锁 指的是以线程为单位 当一个线程获取对象锁之后 这个线程可以再次获取本对象上的锁 而其他的线程是不可以的 synchronized 和 ReentrantLock 都是可重入锁 可重入锁的意义之一在于防止死锁 实现原理实现是通过为每
  • 照片怎样变漫画图片?建议收藏这些方法

    小伙伴们平时喜欢在社交平台上 发布一些照片的动态吗 那有没有发现别人的一些照片动态很好看 有漫画照片 文字照片 边框照片等多种多样的效果 有小伙伴羡慕别的照片问什么这么多样吗 其实你们也可以做到的 只需要使用软件就可以帮助我们完成这些照片编
  • JPM Coin 三部曲 (中) - 摩根大通为何青睐 Quorum 区块链

    本篇是三部曲的第二部分 聊一聊 JPM coin 背后的区块链网络 Quorum 详解其特点 共识机制 及其如何满足传统银行业的商业需求 Quorum 被认为是 企业级以太坊 从2016年起由摩根大通银行启动的开源项目 https gith
  • 为什么有两台计算机WINDOWS,你有两台运行Windows7的计算机分别命名为Computer1和Computer2。这两台计算机都是一个活动目录域的成员,两台计算机上都启用了Windows远程管理...

    YourcompanyhastwodomaincontrollersthatareconfiguredasinternalDNSservers AllzonesontheDNSserversareActiveDirectory integr
  • Git没有权限

    Git 没有权限 出现下面图片错误的 请在系统盘 C盘 找到 用户文件夹 进入后 找到管理员文件夹下有个 gitconfig 删除掉 然后在用命令进行克隆链接 git clone http XXXXX git 自动会跳出让你输入Git用户名
  • Python的学习过程中not enough values to unpack (expected 2, got 1)解决方案

    这是一篇在自学过程中debug的笔记 愿我们一同进步 问题描述 跟着小甲鱼一起学习Python 在学习到 文件 的时候有一个代码任务 内容是根据两个人物之间的三段对话对话进行分割提取操作 运行时报错 主要报错为not enough valu
  • 程序员到底在恐慌什么?

    点击上方 iOS开发 选择 置顶公众号 关键时刻 第一时间送达 程序员们会觉得恐慌么 有时候我会 或者说 现在也会 这种恐慌大概是在上学的时候就有了 上学的时候我不知道怎么入门 去书店里看书 C VisualBasic Java C C P
  • 智慧企业转型升级蓝图 附下载地址

    2020年的猛烈震荡让各行业面临的挑战急剧升级 企业经营更是险中求胜 各行业都在全力转型以谋求突破 对于许多企业来说 数字化重塑不再是种选择 而是种必然 日前 IBM 与各行业专家 首次携手共创了 共创共赢 聚智前行 中国智慧企业转型升级蓝
  • windows忘记mysql5.7密码修改密码

    1 打开第一个cmd窗口执行 net stop mysql57 2 在第一个cmd窗口执行 mysqld defaults file C ProgramData MySQL MySQL Server 5 7 my ini skip gran
  • 机器学习笔记 soft-DTW(论文笔记 A differentiable loss function for time-series)

    1 soft DTW来由 DTW 算法通过动态规划求解了两个序列的相似度 这个过程1是离散的 不可微的 如果要将其应用作为神经网络的损失函数 这是不行的 因为神经网络通过对损失函数结果进行梯度下降的方法 更新参数 要求损失函数可微 2 符号
  • sqlmap详细使用介绍

    SQLmap介绍 sqlmap是一个自动化的SQL注入工具 其主要功能是扫描 发现并利用给定的URL进行SQL注入 目前支持的数据库有MySql Oracle Access PostageSQL SQL Server IBM DB2 SQL
  • redis之单机多节点集群,javaee教程网上购书系统

    bind 192 168 40 142 5 将redis cluster redis01文件复制5份到redis cluster目录下 redis02 redis06 创建6个redis实例 模拟Redis集群的6个节点 然后将其余5个文件
  • html flex 兼容ie9,flex布局及其兼容解决方案_蓝戒的博客

    导语 布局的传统解决方案 基于盒状模型 依赖 display属性 position属性 float属性 它对于那些特殊布局非常不方便 比如 垂直居中就不容易实现 2009年 W3C提出了一种新的方案 Flex布局 可以简便 完整 响应式地实
  • LevelDB源码分析之内存管理类arena

    LevelDB源码分析之内存管理类arena Leveldb的大部分内存管理依赖于C 语言的默认实现 也就是不对内存进行管理 只是在memtable的实现中用到了一个简单的内存管理器 arena 因为memtable的内部实现skip li
  • ElasticSearch6.x 之路由规则

    1 创建文档指定路由 语法规则 http elasticsearch 服务器访问地址 索引名称 文档名称 文档主键编号 routing 路由名称 Put请求 携带文档属性参数 实列 http 192 168 1 74 9200 shoppi
  • @Override异常

    文章目录 异常 异常 异常现象 导入一个新的maven项目发现很奇怪的一个bug 提示错误 Override is not allowed when implementing interface method 异常原因 Override从j
  • PAT乙级1057 数零壹 (20 分)

    1057 数零壹 20 分 一 问题描述 给定一串长度不超过 10 5 的字符串 本题要求你将其中所有英文字母的序号 字母 a z 对应序号 1 26 不分大小写 相加 得到整数 N 然后再分析一下 N 的二进制表示中有多少 0 多少 1
  • 使用Java实现JDBC 驱动程序,连接本地文件

    要使用Java实现JDBC驱动程序以连接您的本地文件 您可以使用H2数据库提供的嵌入式数据库引擎 import java sql import java util Properties public class LocalFileDrive
  • 回归评估指标:MSE、R2

    原数据标签 预测结果 平均值 1 均方误差 MSE Mean Squared Error 2 均方根误差 RMSE 对MSE开平方 3 R2 R Square 注 R2一般取 0 1 0表示拟合效果不好 如果出现负值 首先考虑数据集是否有问
  • 读书笔记 -《Python 黑帽子》 ( 二 )

    读书笔记系列文章 一直都在读书 读了忘 忘了再读 不如把每次学到的东西都写下来 第三章 网络 原始套接字和流量嗅探 我的工作内容就是用C 语言写嗅探工具和 DPI 基本的工作原理和本章的内容是非常相似的 所以理解起来会比较容易一些 arp