Black Hat Python书中的Python嗅探 [英] Python Sniffing from Black Hat Python book

查看:111
本文介绍了Black Hat Python书中的Python嗅探的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import socket
import os
import struct
import sys
from ctypes import *

# host to listen on
host   = sys.argv[1]

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)

这是《黑帽Python》一书中的代码.此代码应该使用原始套接字进行嗅探并显示来自 IP 标头的信息.在Windows(使用Windows 8.1 64位)上对我来说效果很好.当我尝试在Linux(Kali linux 1.1.0-amd64)上运行此命令时,出现以下错误

This is code from the book Black Hat Python. This code is supposed to sniff with raw sockets and display information from the IP header. It works fine for me on Windows (using Windows 8.1 64bit). When I attempt to run this on linux (Kali linux 1.1.0-amd64) I get the following error

ValueError: Buffer size too small (20 instead of at least 32 bytes)

为了解决这个问题,我像这样在缓冲区中添加了12个空格

To get around that I added 12 spaces to the buffer like this

ip_header = IP(raw_buffer[0:20]+' '*12)

当我这样做时,出现以下错误

When I do that I get the following error

struct.error: 'L' format requires 0 <= number <= 4294967295

这是在线发生的

self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))

我尝试将L之前的符号更改为>和!我只用L尝试了一下,所有人都给了我同样的问题.我也尝试过将self.src包裹在ntohs中,

I have tried changing the symbol before the L to > and ! and I tried it with just L all of them give me the same issue. I also tried wrapping self.src in ntohs like so

self.src_address = socket.inet_ntoa(struct.pack("<L",socket.ntohs(self.src)))

我认为这与字节序有关,但我不确定.任何帮助将不胜感激.

I'm thinking this has something to do with endianness but I'm not sure. Any help would be greatly appreciated.

注意:由于原始套接字,在Windows上必须以管理员身份运行,而在Linux上则必须以超级用户身份运行.如果您在Linux上运行此命令,请打开另一个终端并ping www.google.com,以便可以生成一些ICMP数据包以供捕获.

NOTE: On windows you have to run as an administrator and on linux you have to run as a superuser because of the raw sockets. If you run this on linux open up another terminal and ping www.google.com so you can generate some ICMP packets for it to capture.

我也尝试过用

ip_header = IP(raw_buffer[0:20][::-1]+' '*12)

在执行我在此处列出的其他任何项目之前,我确实尝试了以下行的65535和65534.

EDIT 2: I did try both 65535 and 65534 on the below line before doing any of the other items I listed here.

raw_buffer = sniffer.recvfrom(65565)[0]

这可以在运行python 2.7.6的ubuntu机器上工作,而我的kali发行版是2.7.3,所以我决定在我的kali盒上获得最新版本的python,恰好是2.7.9.还是没有运气.

EDIT 3: This worked on an ubuntu machine running python 2.7.6 and my kali distro was 2.7.3 so I decided to get the latest version of python on my kali box which happens to be 2.7.9. Still no luck.

我将以下代码放置到结构中的 new 函数中,以查看缓冲区大小

I placed the following code to the new function in my structure to view the buffer size

print sizeof(self)

在我的Ubuntu和Windows机器上是20,但是在我的kali机器上是32

On my Ubuntu and windows machines it was 20 however on my kali machine it was 32

推荐答案

#raw_buffer = sniffer.recvfrom(65565)[0]
raw_buffer = sniffer.recvfrom(65535)[0]

IP包大小为(2 ^ 16)-1

IP paket size is (2^16) - 1

问题出在32位和64位系统上.
ip_header = IP(raw_buffer [:20])可在x86 Ubuntu上使用.
ip_header = IP(raw_buffer [:32])在amd64 CentOS 6.6 Python 2.6.6上运行 ip_header = IP(raw_buffer)都可以使用.

The problem is with 32 vs 64 bit systems.
ip_header = IP(raw_buffer[:20]) works on x86 Ubuntu.
ip_header = IP(raw_buffer[:32]) works on amd64 CentOS 6.6 Python 2.6.6
ip_header = IP(raw_buffer) works in both.

您必须更改它们,

("src",           c_ulong),
("dst",           c_ulong)  

self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))

进入

("src",           c_uint32),
("dst",           c_uint32)  

self.src_address = socket.inet_ntoa(struct.pack("@I",self.src))
self.dst_address = socket.inet_ntoa(struct.pack("@I",self.dst))

'@ I'是按本机顺序单整数int.因为 c_ulong 在i386中为4个字节,在amd64中为8个字节.检查以下内容,

'@I' is unisigned int in native order. because c_ulong is 4 bytes in i386 and 8 in amd64. Check the following,

struct.calcsize('@BBHHHBBHLL')  

在i386中为20,在amd64中为32,其大小为 _fields _ .实际上,它是amd64中的28个字节,外加4个字节以进行字对齐.

is 20 in i386 and 32 in amd64 which is size of _fields_. In actual it's 28 bytes in amd64 plus 4 bytes padded for word alignment.

ip_header = IP(raw_buffer [:20])现在可以独立于平台正常工作.

ip_header = IP(raw_buffer[:20]) now works correctly independent of platforms.

这篇关于Black Hat Python书中的Python嗅探的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆