Python:解包

时间:2016-07-20 02:17:10

标签: python python-3.x

我正在使用Python编写一个程序但是当我通过终端运行时出现以下错误:

Traceback (most recent call last):
  File "packetSniffer.py", line 120, in <module>
    main()
  File "packetSniffer.py", line 27, in main
    (version, headerLength, timeToLive, protocol, source, target, data) = ip(data)
ValueError: too many values to unpack (expected 7)

然而,我正在以正确的方式做所有事情(我假设因为我没有看到我的代码有任何问题)。我希望一双新的眼睛能够发现我的问题。

这是我的整个计划:

import struct
import textwrap
import socket

TAB_1 = '\t - '
TAB_2 = '\t\t - '
TAB_3 = '\t\t\t - '
TAB_4 = '\t\t\t\t - '

DATA_TAB_1 = '\t   '
DATA_TAB_2 = '\t\t   '
DATA_TAB_3 = '\t\t\t   '
DATA_TAB_4 = '\t\t\t\t   '


def main():
    connection = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(3))

    while True:
        rawData, address = connection.recvfrom(65535)
        reciever_mac, sender_mac, ethernetProtocol, data = ethernet_frame(rawData)
        print('\nEthernet Frame: ')
        print(TAB_1 + 'Destination: {}, Source: {}, Protocol: {}'.format(reciever_mac, sender_mac, ethernetProtocol))

        #Make sure you are using Ethernet protocol 8
        if ethernetProtocol == 8:
            (version, headerLength, timeToLive, protocol, source, target, data) = ip(data)
            print(TAB_1 + 'IP Packet:')
            print(TAB_2 + 'Version: {}, Header Length: {}, TTL: {}'.format(version, headerLength, timeToLive))
            print(TAB_2 + 'Protocol: {}, Source: {}, Target: {}'.format(protocol, source, target))

            if protocol == 1:
                icmpType, code, checkSum, data = icmpPackets(data)
                print(TAB_1 + 'ICMP Packet:')
                print(TAB_2 + 'Type: {}, Code: {}, Checksum: {},'.format(icmpType, code, checkSum))
                print(TAB_2 + 'Data:')
                print(formatMultiLine(DATA_TAB_3, data))

            elif protocol == 6:
                (sourcePort, destinationPort, sequence, acknowledgement, flagURG, flagACK, flagPSH, flagRST, flagSYN, flagFIN, data) = tcpSegment(data)
                print(TAB_2 + 'Source Port: {}, Destination Port: {}'.format(sourcePort, destinationPort))
                print(TAB_2 + 'Sequence: {}, Acknowledgment: {}'.format(sequence, acknowledgement))
                print(TAB_2 + 'Flags:')
                print(TAB_3 + 'URG: {}, ACK: {}, PSH: {}'.format(flagURG, flagACK, flagPSH))
                print(TAB_3 + 'RST: {}, SYN: {}, FIN:{}'.format(flagRST, flagSYN, flagSYN))
                print(formatMultiLine(DATA_TAB_3, data))

            elif protocol == 17:
                (sourcePort, destinationPort, length, data) = udpSegment(data)
                print(TAB_1 + 'UDP Segment:')
                print(TAB_2 + 'Source Port: {}, Destination Port: {}, Length: {}'.format(sourcePort, destinationPort, length))

            else:
                print(TAB_1 + 'Other IPv4 Data:')
                print(formatMultiLine(DATA_TAB_2, data))

        else:
            print('Ethernet Data:')
            print(formatMultiLine(DATA_TAB_1, data))


# Unpack ethernet frame
def ethernet_frame(data):
    reciever_mac, sender_mac, protocol = struct.unpack('! 6s 6s H', data[:14])
    return getMacAddress(reciever_mac), getMacAddress(sender_mac), socket.htons(protocol), data[14:]

# Convert the Mac address from the jumbled up form from above into human readable format
def getMacAddress(bytesAddress):
    bytesString = map('{:02x}'.format, bytesAddress)
    macAddress = ':'.join(bytesString).upper()
    return macAddress

#Unpack IP header data
def ip_packet(data):
    versionHeaderLength = data[0]
    version = versionHeaderLength >> 4
    headerLength = (versionHeaderLength & 15) * 4

    timeToLive, protocol, source, target = struct.unpack('! 8x B B  2x 4s 4s', data[:20])
    return version, headerLength, timeToLive, protocol, ip(source), ip(target), data[headerLength:]

#Returns properly formatted IP address
def ip(address):
    return '.'.join(map(str, address))

#Unpack ICMP packets
def icmpPackets(data):
    icmpType, code, checkSum = struct.unpack('! B B H', data[:4])
    return icmpType, code, checkSum, data[4:]

#Unpack TCP segments:
def tcpSegment(data):
    (sourcePort, destinationPort, sequence, acknowledgement, offsetReservedFlags) = struct.unpack('! H H L L H', data[:14])
    offset = (offsetReservedFlags >> 12) * 4

    flagURG = (offsetReservedFlags & 32) >> 5
    flagACK = (offsetReservedFlags & 16) >> 4
    flagPSH = (offsetReservedFlags & 8) >> 3
    flagRST = (offsetReservedFlags & 4) >> 2
    flagSYN = (offsetReservedFlags & 2) >> 1
    flagFIN = offsetReservedFlags & 1

    return sourcePort, destinationPort, sequence, acknowledgement, flagURG, flagACK, flagPSH, flagRST, flagSYN, flagFIN, data[offset:]

#Unpack UDP segments:
def udpSegment(data):
    sourcePort, destinationPort, size = struct.unpack('! H H 2x H', data[:8])
    return sourcePort, destinationPort, size, data[8:]

#Breaks down and formats large, multi-lined data
def formatMultiLine(prefix, string, size = 80):
    size -= len(prefix)
    if isinstance(string, bytes):
        string = ''.join(r'\x{:02X}'.format(byte) for byte in string)
        if size % 2:
            size -= 1

    return '\n'.join([prefix + line for line in textwrap.wrap(string, size)])

main()

提前致谢!

3 个答案:

答案 0 :(得分:0)

这似乎是ip(data)返回一个超过7个elems的seq。 试试这个:

<?php
    $con = mysqli_connect("*****", "****", "***", "***");

    $username = $_POST["username"];
    $title = $_POST["title"];
    $description = $_POST["description"];
    $location = $_POST["location"];
    $cost = $_POST["cost"];
    $obo = $_POST["obo"];
    $dimmension = $_POST["dimmension"];
    $phone = $_POST["phone"];
    $email = $_POST["email"];
    $image = $_POST["image"];
    $image2 = $_POST["image2"];

    $statement = mysqli_prepare($con, "SELECT username,title,description,location,cost,obo,dimmension,phone,email,image,image2 FROM Postings");
    mysqli_stmt_bind_param($statement, $username,$title,$description,$location,$cost,$obo,$dimmension,$phone,$email,$image,$image2);
    mysqli_stmt_execute($statement);

    mysqli_stmt_store_result($statement);
    mysqli_stmt_bind_result($statement, $username,$title,$description,$location,$cost,$obo,$dimmension,$phone,$email,$image,$image2);

    $response = array();

    while(mysqli_stmt_fetch($statement)){  
        $response[] = $username;
    }

    $response["success"] = true; 
    #echo json_encode($respond);
    echo json_encode($response);
?>

答案 1 :(得分:0)

在错误线之前:

database

你应该放置以下内容:

(version, headerLength, timeToLive, protocol, source, target, data) = ip(data)

然后它的输出应该显示完全问题是什么 - 这是调试101的东西,它几乎始终更好地获得更多信息在尝试调试代码时减少。

在这种情况下,它几乎可以保证print(data) print(ip(data)) 将返回多个其他的项目。

答案 2 :(得分:0)

这里的问题是你的ip函数只返回一个字符串,但你要提取一堆简单无法通过解压缩提取的东西,你需要重新定义ip函数返回所有内容或更改使用方式。

顺便说一下,有一种方法可以在更大的序列中通过在{1}}中使用*将所有剩余的东西放在你的解压缩列表python中的一个变量中进行一些计算,以便每个人都得到了要解压缩的数据

>>> test="255.255.255.255"
>>> a,b,c,d,e,f,g,*h=test
>>> a
'2'
>>> b
'5'
>>> c
'5'
>>> d
'.'
>>> h
['.', '2', '5', '5', '.', '2', '5', '5']
>>> 
>>> *a,b,c,d,e,f,g,h=test
>>> a
['2', '5', '5', '.', '2', '5', '5', '.']
>>> b
'2'
>>> c
'5'
>>> a,b,*c,d,e,f,g,h=test
>>> a
'2'
>>> b
'5'
>>> c
['5', '.', '2', '5', '5', '.', '2', '5']
>>> d
'5'
>>>      

正如您所看到的,解压缩字符串只会给你一个字符...