为了账号安全,请及时绑定邮箱和手机立即绑定

将Python2脚本移植到Python3 - struct库

将Python2脚本移植到Python3 - struct库

Qyouu 2023-09-05 15:21:56
我正在开发一个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 & 0xffffffffcsum = csum & 0xffffffff我删除了行尾的 L。谁能帮我移植这个 ICMP.py 脚本并解释一下?
查看完整描述

1 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

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


这是编辑后的代码:


#!/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。


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


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


查看完整回答
反对 回复 2023-09-05
  • 1 回答
  • 0 关注
  • 85 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信