You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行constructs.py遇TypeError:PascalString缺失encoding参数求助

修复PascalString()缺少encoding参数的错误

PascalString() missing 1 required positional argument: 'encoding'

运行他人编写的constructs.py脚本时出现上述错误,以下是完整脚本代码与错误详情:

constructs.py

from construct import (
    Array,
    Bytes,
    Struct,
    VarInt,
    Int8ub,
    Int16ub,
    Int24ub,
    Int32ub,
    PascalString,
    Prefixed,
    GreedyRange,
    Switch,
    Optional,
)

ProtocolVersion = "version" / Struct(
    "major" / Int8ub,
    "minor" / Int8ub,
)

TLSPlaintext = "TLSPlaintext" / Struct(
    "type" / Int8ub,
    ProtocolVersion,
    "length" / Int16ub,
    "fragment" / Bytes(lambda ctx: ctx.length),
)

TLSCompressed = "TLSCompressed" / Struct(
    "type" / Int8ub,
    ProtocolVersion,
    "length" / Int16ub,
    "fragment" / Bytes(lambda ctx: ctx.length),
)

TLSCiphertext = "TLSCiphertext" / Struct(
    "type" / Int8ub,
    ProtocolVersion,
    "length" / Int16ub,
    "fragment" / Bytes(lambda ctx: ctx.length),
)

Random = "random" / Struct(
    "gmt_unix_time" / Int32ub,
    "random_bytes" / Bytes(28),
)

SessionID = "session_id" / Struct(
    "length" / Int8ub,
    "session_id" / Bytes(lambda ctx: ctx.length),
)

CipherSuites = "cipher_suites" / Struct(
    "length" / Int16ub,
    Array(lambda ctx: ctx.length // 2, "cipher_suites" / Int16ub),
)

CompressionMethods = "compression_methods" / Struct(
    "length" / Int8ub,
    Array(lambda ctx: ctx.length, "compression_methods" / Int8ub),
)

ServerName = Struct(
    "type" / Int8ub,
    "name" / PascalString("length" / Int16ub),
)

SNIExtension = Prefixed(
    Int16ub,
    Struct(
        Int16ub,
        "server_names" / GreedyRange(
            "server_name" / Struct(
                "name_type" / Int8ub,
                "host_name" / PascalString("length" / Int16ub),
            )
        )
    )
)

ALPNExtension = Prefixed(
    Int16ub,
    Struct(
        Int16ub,
        "alpn_protocols" / GreedyRange(
            "name" / PascalString(Int8ub),
        ),
    )
)

UnknownExtension = Struct(
    "bytes" / PascalString("length" / Int16ub)
)

Extension = "Extension" / Struct(
    "type" / Int16ub,
    Switch(
        lambda ctx: ctx.type,
        {
            0x00: SNIExtension,
            0x10: ALPNExtension,
        },
        default=UnknownExtension
    )
)

extensions = "extensions" / Struct(
    Int16ub,
    "extensions" / GreedyRange(Extension)
)

ClientHello = "ClientHello" / Struct(
    ProtocolVersion,
    Random,
    SessionID,
    CipherSuites,
    CompressionMethods,
    extensions,
)

ServerHello = "ServerHello" / Struct(
    ProtocolVersion,
    Random,
    SessionID,
    "cipher_suite" / Bytes(2),
    "compression_method" / Int8ub,
    extensions,
)

ClientCertificateType = "certificate_types" / Struct(
    "length" / Int8ub,
    Array(lambda ctx: ctx.length, "certificate_types" / Int8ub),
)

SignatureAndHashAlgorithm = "algorithms" / Struct(
    "hash" / Int8ub,
    "signature" / Int8ub,
)

SupportedSignatureAlgorithms = "supported_signature_algorithms" / Struct(
    "supported_signature_algorithms_length" / Int16ub,
    # TODO: Reject packets of length 0
    Array(
        lambda ctx: ctx.supported_signature_algorithms_length / 2,
        SignatureAndHashAlgorithm,
    ),
)

DistinguishedName = "certificate_authorities" / Struct(
    "length" / Int16ub,
    "certificate_authorities" / Bytes(lambda ctx: ctx.length),
)

CertificateRequest = "CertificateRequest" / Struct(
    ClientCertificateType,
    SupportedSignatureAlgorithms,
    DistinguishedName,
)

ServerDHParams = "ServerDHParams" / Struct(
    "dh_p_length" / Int16ub,
    "dh_p" / Bytes(lambda ctx: ctx.dh_p_length),
    "dh_g_length" / Int16ub,
    "dh_g" / Bytes(lambda ctx: ctx.dh_g_length),
    "dh_Ys_length" / Int16ub,
    "dh_Ys" / Bytes(lambda ctx: ctx.dh_Ys_length),
)

PreMasterSecret = "pre_master_secret" / Struct(
    ProtocolVersion,
    "random_bytes" / Bytes(46),
)

ASN1Cert = "ASN1Cert" / Struct(
    "length" / Int32ub,
    "asn1_cert" / Bytes(lambda ctx: ctx.length),
)

Certificate = "Certificate" / Struct(
    # TODO: Reject packets with length > 2 ** 24 - 1
    "certificates_length" / Int32ub,
    "certificates_bytes" / Bytes(lambda ctx: ctx.length),
)

Handshake = "Handshake" / Struct(
    "msg_type" / Int8ub,
    "length" / Int24ub,
    "body" / Bytes(lambda ctx: ctx.length),
)

Alert = "Alert" / Struct(
    "level" / Int8ub,
    "description" / Int8ub,
)

错误信息

File "/root/bdfproxy/mitmproxy/mitmproxy/contrib/tls/_constructs.py", line 71, in <module>
    "name" / PascalString("length" / Int16ub),
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: PascalString() missing 1 required positional argument: 'encoding'

修复方案

错误原因是当前使用的construct库版本较新,而原脚本基于旧版本编写。新版本中PascalString必须传入encoding参数指定字符串编码。

需要修改脚本中所有PascalString的调用,添加编码参数(TLS协议相关字段通常用'ascii',也可根据实际需求用'utf-8'):

  1. ServerName结构体:
ServerName = Struct(
    "type" / Int8ub,
    "name" / PascalString("length" / Int16ub, encoding='ascii'),
)
  1. SNIExtension中的host_name字段:
"host_name" / PascalString("length" / Int16ub, encoding='ascii'),
  1. ALPNExtension中的name字段:
"name" / PascalString(Int8ub, encoding='ascii'),
  1. UnknownExtension结构体:
UnknownExtension = Struct(
    "bytes" / PascalString("length" / Int16ub, encoding='ascii')
)

备选方案:降级construct库

如果不想修改代码,可以降级到不需要encoding参数的旧版本(比如construct<2.10),执行命令:

pip install construct==2.9.52

内容的提问来源于stack exchange,提问作者MadDemon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:47:32