【问题标题】:Porting Python2 script to Python3 - struct library将 Python2 脚本移植到 Python3 - 结构库
【发布时间】:2021-01-11 16:37:36
【问题描述】:

我正在开发一个 socks5 代理服务器,现在我正在实施一种 ICMP 隧道方法来通过 ICMP 协议隧道 SSH 流量以绕过防火墙限制。

这是我使用的开源:https://github.com/sanecz/pingtunnel

    def create(self):
        pack_str = "!BBHHH4sH"
        pack_args = [self.type, self.code, 0, self.id, self.sequence,
                     socket.inet_aton(self.dest[0]), self.dest[1]]

        if self.length:
            pack_str += "{}s".format(self.length)
            pack_args.append(self.data)

        self.checksum = self._checksum(struct.pack(pack_str, *pack_args)) 
        pack_args[2] = self.checksum
        return struct.pack(pack_str, *pack_args)

这部分代码给我带来了麻烦,我必须在 python3 中运行这段代码才能匹配我的 Socks5 代理和反向端口转发。

self.checksum = self._checksum(struct.pack(pack_str, *pack_args))

这一行给了我一个“期望值不是 int”的错误。

也在这里:

        while count < countTo:
            thisVal = ord(packet[count+1]) * 256 + ord(packet[count])
            csum = csum + thisVal
            csum = csum & 0xffffffff
            count = count + 2

        if countTo < len(packet):
            csum = csum + ord(packet[len(packet) - 1])
            csum = csum & 0xffffffff

我删除了 csum = csum &amp; 0xffffffff 行的 L 结尾。

谁能帮我移植这个 ICMP.py 脚本并解释一下?

【问题讨论】:

  • 在第一个 sn-p 中,我相信错误消息意味着 pack_args 中的一个值应该是 int,但不是。您的问题中没有足够的信息来确定哪一个在 Python 2 和 3 之间发生了变化。

标签: python python-3.x python-2.7 porting


【解决方案1】:

嘿伙计们,我尝试了几次后自己解决了这个问题!

这是编辑后的代码:

#!/usr/bin/python3

import socket
import struct

ICMP_ECHO = 0
ICMP_ECHO_REQUEST = 8

class ICMPPacket(object):
    def __init__(self, type, code, checksum, id,
                 sequence, data, source_ip, dest=(None, None)):
        self.type, self.code, self.checksum = type, code, checksum
        self.id, self.sequence, self.data = id, sequence, data
        self.dest = dest
        self.source_ip = source_ip
        self.length = len(self.data)

    def __repr__(self):
        return "<ICMP packet: type = {s.type}, code = {s.code}, " \
            "data length = {length}".format(s=self, length=len(self.data))

    def __str__(self):
        return "Type of message: {s.type}, Code {s.code},"\
            "Checksum: {s.checksum}, ID: {s.id}, Sequence: {s.sequence}, " \
            "Data: {s.data}, Data length: {length}".format(s=self, length=len(self.data))

    def create(self):
        #print("\nEntering CREATE!!\n\n")
        pack_str = "!BBHHH4sH"
        pack_args = [self.type, self.code, 0, self.id, self.sequence,
                     socket.inet_aton(self.dest[0]), self.dest[1]]

        if self.length:
            pack_str += "{}s".format(self.length)
            #print("PACK STR: " + pack_str)
            pack_args.append(self.data)

        #print("Pack ARGS: \n", pack_args, "\n")
        self.checksum = self._checksum(struct.pack(pack_str, *pack_args)) 
        #print("CHECKSUM: ", self.checksum)
        pack_args[2] = self.checksum
        return struct.pack(pack_str, *pack_args)

    @classmethod
    def parse(cls, packet):
        ip_pack_str = "BBHHHBBH4s4s"
        icmp_pack_str = "!BBHHH4sH"
        data = ""

        ip_packet, icmp_packet = packet[:20], packet[20:] # split ip header

        ip_packet = struct.unpack(ip_pack_str, ip_packet)

        source_ip = ip_packet[8]
        icmp_pack_len = struct.calcsize(icmp_pack_str)
        packet_len = len(icmp_packet) - icmp_pack_len

        if packet_len > 0:
            icmp_data_str = "{}s".format(packet_len)
            data = struct.unpack(icmp_data_str, icmp_packet[icmp_pack_len:])[0]

        type, code, checksum, id, sequence, dest_ip, \
            dest_port = struct.unpack(icmp_pack_str, icmp_packet[:icmp_pack_len])

        return cls(type, code, checksum, id, sequence, data,
                   socket.inet_ntoa(source_ip),
                   (socket.inet_ntoa(dest_ip), dest_port))


    @staticmethod
    def _checksum(packet):
        #print("Argument for checksum: !!\n",packet)
        packet = packet.decode('ISO-8859-1') # edited to match python3 
        csum = 0
        countTo = (len(packet) / 2) * 2
        count = 0

        while count < countTo:
            thisVal = ord(packet[count+1]) * 256 + ord(packet[count])
            #print("THISVAL: ", thisVal)
            csum = csum + thisVal
            csum = csum & 0xffffffff
            count = count + 2

        if countTo < len(packet):
            csum = csum + ord(packet[len(packet) - 1])
            csum = csum & 0xffffffff

        csum = (csum >> 16) + (csum & 0xffff)
        csum = csum + (csum >> 16)
        checksum = ~csum
        checksum = checksum & 0xffff
        checksum = checksum >> 8 | (checksum << 8 & 0xff00)
        return checksum

我使用packet = packet.decode('ISO-8859-1')重新编码数据包以匹配字节

为了匹配这一行thisVal = ord(packet[count+1]) * 256 + ord(packet[count])

因为它需要一个字符串,而它却收到了一个 INT。

因此将其解码为字符串解决了这个问题!

编辑:如果您对更好的编码来处理数据包的二进制数据有任何建议,请告诉我。

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    相关资源
    最近更新 更多