python黑编——IP包嗅探

1、附上源码

import socket
import os
import struct
from ctypes import *

# 本地监听
host   = "127.0.0.1"

#IP头定义
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):

        # 协议字段与协议名称对应
        self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}

        # human readable IP addresses
        self.src_address = socket.inet_ntoa(struct.pack(" %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)

2、源码解读

ctype库

python的底层大部分都是C/C++实现,python赋予了黑客类似于c语言一样的底层操作能力,且不失动态语言的便捷;

python访问C/C++的方式很多(ctypes,pybind11,cffi,swig),但ctypes是最方便的;

ctype库提供了和C语言兼容的数据类型和函数来加载dll文件,因此在调用时不需对源文件做任何的修改。

python黑编——IP包嗅探_第1张图片

用ctype库加载dll文件

import platform
from ctypes import *

if platform.system() == 'Windows':
    libc = cdll.LoadLibrary('msvcrt.dll')
elif platform.system() == 'Linux':
    libc = cdll.LoadLibrary('libc.so.6')

libc.printf('%s\n', 'here!')        
libc.printf('%S\n', u'there!')      

struct模块

可以按照指定格式将Python数据和字节流进行转换;可以处理c语言中的结构体。

structpack函数把任意数据类型变成bytes:

pack(fmt,v1,v2…)

按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.

struct.pack("

fmt格式——对齐方式

python黑编——IP包嗅探_第2张图片

fmt格式——格式符

python黑编——IP包嗅探_第3张图片

IP结构

python黑编——IP包嗅探_第4张图片

Socket模块中一些IP转换函数

socket.ntohl(x)         // 类似于C语言的ntohl(x)

把32位正整数从网络序转换成主机字节序。

socket.ntohs(x)        // 类似于C语言的ntohs(x)

把16位正整数从网络序转换成主机字节序。

socket.htonl(x)         // 类似于C语言的htonl(x)

把32位正整数从主机字节序转换成网络序。

socket.htons(x)        // 类似于C语言的htons(x)

把16位正整数从主机字节序转换成网络序。

socket.inet_aton(ip_string)  // 依赖于inet_aton的C实现

转换IPV4地址字符串(192.168.10.8)成为32位打包的二进制格式(长度为4个字节的二进制字符串),它不支持IPV6。inet_pton()支持IPV4/IPV6地址格式。

socket.inet_ntoa(packed_ip)

转换32位打包的IPV4地址为IP地址的标准点号分隔字符串表示。

socket.inet_pton(address_family,ip_string)

转换IP地址字符串为打包二进制格式。地址家族为AF_INET和AF_INET6,它们分别表示IPV4和IPV6。

socket.inet_ntop(address_family,packed_ip)

转换一个打包IP地址为标准字符串表达式,例如:“5aef:2b::8”或“127.0.0.1”。
以上来自于https://blog.csdn.net/fan_hai_ping/article/details/8435140

 

你可能感兴趣的:(python)