【问题标题】:How to properly unpack a RAW socket on Win10 using Python?如何使用 Python 在 Win10 上正确解包 RAW 套接字?
【发布时间】:2018-06-23 10:56:43
【问题描述】:

我有适用于 Linux 的工作代码,但在 Windows 上我得到了意想不到的结果。 代码:

import socket
import sys
from struct import unpack
import platform


def main():
    local_ip = socket.gethostbyname(socket.gethostname())
    print local_ip
    try:
        if platform.system() == 'Linux':
            s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
                              socket.ntohs(0x0003))
        elif platform.system() == 'Windows':
            s = socket.socket(socket.AF_INET, socket.SOCK_RAW,
                              socket.IPPROTO_IP)
            s.bind((local_ip, 0))
            s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
            s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
        else:
            sys.exit()
    except socket.error as msg:
        print('Socket could not be created. Error Code : ' + str(
            msg[0]) + ' Message ' + msg[1])
        sys.exit()

    # receive a packet
    i = 0
    while i < 10:
        i += 1
        packet = s.recvfrom(65565)
        # packet string from tuple
        packet = packet[0]
        # parse ethernet header
        eth_length = 14
        eth_header = packet[:eth_length]
        eth = unpack('!6s6sH', eth_header)
        eth_protocol = socket.ntohs(eth[2])
        ip_header = packet[eth_length:20 + eth_length]
        # unpack header
        iph = unpack('!BBHHHBBH4s4s', ip_header)
        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xF
        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8])
        d_addr = socket.inet_ntoa(iph[9])
        print 'Header protocol:', eth[2], 'Unpacked protocol:', eth_protocol
        print 'Version : ' + str(
            version) + ' IP Header Length : ' + str(
            ihl) + ' TTL : ' + str(
            ttl) + ' Protocol : ' + str(
            protocol) + ' Source Address : ' + str(
            s_addr) + ' Destination Address : ' + str(d_addr)


if __name__ == '__main__':
    main()

我拿了this as example

所以,在 Linux 上我得到了预期的数据

127.0.1.1 标头协议:2048 解包协议:8 版本:4 IP 标头长度:5 TTL:64 协议:17 源地址:127.0.0.1 目标地址:127.0.0.53 标头协议:2048 未打包 协议:8 版本:4 IP 头长度:5 TTL:64 协议:17 源地址:127.0.0.1 目标地址:127.0.0.53 标头 协议:2048 解包协议:8 版本:4 IP 标头长度:5 TTL:64 协议:17 源地址:127.0.0.53 目标地址 :127.0.0.1 标头协议:2048 解包协议:8 版本:4 IP 标头长度:5 TTL:64 协议:17 源地址:127.0.0.53 目标地址:127.0.0.1 标头协议:2048 解压 协议:8 版本:4 IP 标头长度:5 TTL:64 协议:6强> 源地址:10.0.2.15 目的地址:5.196.61.211

但在 Windows 上所有字段都不正确

10.0.2.15

标头协议:2560 解包协议:10 版本:0 IP 标头 长度:2 TTL:8 协议:70 源地址:183.96.34.40 目标地址:36.2.80.16 标头协议:2560 未打包 协议:10 版本:0 IP 标头长度:2 TTL:8 协议:70 源地址:183.96.34.40 目标地址:36.2.80.16 报头 协议:2560 解包协议:10 版本:0 IP 标头长度:2 TTL:8 协议:70 源地址:183.96.34.40 目标 地址:36.3.80.16 标头协议:2560 解包协议:10 版本:0 IP 标头长度:2 TTL:8 协议:70 源地址 :183.96.34.40 目标地址:36.3.80.16 标头协议:2560 解压协议:10 版本:0 IP头长度:2 TTL:8 协议:70 源地址:183.96.34.40 目的地址: 36.3.80.17

我怎样才能得到正确的数据?

附言。我知道 pypcap、scapy 等,但我需要没有任何第三方库的原始数据解析器。如果可能的话,当然可以。

PPS。我在这里查看了所有类似的主题,但仍未找到解决方案

很多人

【问题讨论】:

    标签: python sockets packet-sniffers raw-sockets


    【解决方案1】:

    在 Linux 上,您使用 SOCK_RAWAF_PACKET 来嗅探第 2 层,这意味着您首先获得第 2 层信息(以太网),然后是第 3 层信息(IP)。在 Windows 上,您使用AF_INET 嗅探第 3 层,这意味着您没有获得任何第 2 层信息。尽管如此,您的代码在这两种情况下都假定第 2 层信息(以太网)。
    因此,解决此问题的一种方法是跳过处理 Windows 上的任何以太网信息,因为没有任何以太网信息并立即从 IP 标头开始。

    【讨论】:

    • 谢谢,我没想到这个。您可能知道 - 我如何在 Windows 上获取第 2 层信息?因为我在 Windows 上没有 AF_PACKET。
    • @stahh:您的问题已得到解答,而您现在要问的是另一个问题。请不要在评论中提出新问题,而是创建一个真正的新问题,以便您可以从新问题的更多可见性中获益,而其他人可以从寻找这个新问题的答案中获益。您不能指望其他人在另一个问题的 cmets 中搜索新的问题和答案。
    • 谢谢。最后我找到了答案:不幸的是,有些平台不提供对低级网络层的访问,这适用于 windows,可能适用于 OS X。
    • scapy pypcap...确实提出了低级网络层,感谢winpcap / npcap
    猜你喜欢
    • 2012-04-29
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 2020-10-20
    • 2019-05-05
    • 2012-10-21
    • 2013-01-28
    • 1970-01-01
    相关资源
    最近更新 更多