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

Python/Scapy中Bytes转String失败问题求助

解决Scapy解析DNS NAPTR记录rdata的字节转字符串问题

在使用Scapy发送DNS NAPTR(类型35)查询并捕获响应后,提取到的rdata是二进制Bytes类型,直接使用.decode()或str()转换会得到包含大量转义字符的字符串,无法得到可读的NAPTR记录内容。

问题原因

DNS NAPTR记录的rdata并非纯文本字符串,而是符合RFC 3403定义的结构化二进制数据,包含多个字段(Order、Preference、Flags、Service、Regexp、Replacement),其中穿插空字节(\x00)、长度前缀等控制字符,直接整体转码无法解析出有效内容。

解决方案

方法1:利用Scapy自带的NAPTR解析类

Scapy内置了DNSNAPTRRR类专门用于解析NAPTR记录,无需手动处理原始二进制数据:

from scapy.all import *

# 构造并发送NAPTR查询
dns = IP()/UDP()/DNS()
dns[IP].dst = "194.25.0.70"
dns["DNS Question Record"].qname = "12354987.xxxx.xxxx.de"
dns["DNS Question Record"].qtype = 35

ans, unans = sr(dns)

# 获取解析后的NAPTR记录(自动映射为DNSNAPTRRR对象)
naptr_record = ans[0][1][DNS].an

# 提取并打印各个可读字段
print(f"Order: {naptr_record.order}")
print(f"Preference: {naptr_record.preference}")
print(f"Flags: {naptr_record.flags.decode('ascii')}")
print(f"Service: {naptr_record.service.decode('ascii')}")
print(f"Regexp: {naptr_record.regexp.decode('ascii')}")
print(f"Replacement: {naptr_record.replacement.decode('ascii')}")

方法2:手动解析原始rdata(如果需要处理二进制数据)

如果必须手动拆分原始rdata,可按照RFC 3403的格式逐个字段解析:

naptr = ans[0][1][UDP][DNS][DNSRR].rdata

# 解析Order(2字节,大端)
order = int.from_bytes(naptr[:2], byteorder='big')
# 解析Preference(2字节,大端)
preference = int.from_bytes(naptr[2:4], byteorder='big')
# 解析Flags(从第4字节到第一个\x00)
flags_end = naptr.index(b'\x00', 4)
flags = naptr[4:flags_end].decode('ascii')
# 解析Service(从flags结束的下一个字节到下一个\x00)
service_start = flags_end + 1
service_end = naptr.index(b'\x00', service_start)
service = naptr[service_start:service_end].decode('ascii')
# 解析Regexp(从service结束的下一个字节到下一个\x00)
regexp_start = service_end + 1
regexp_end = naptr.index(b'\x00', regexp_start)
regexp = naptr[regexp_start:regexp_end].decode('ascii')
# 解析Replacement(DNS域名格式,长度前缀+标签,以\x00结尾)
replacement_start = regexp_end + 1
replacement_parts = []
pos = replacement_start
while naptr[pos] != 0:
    label_len = naptr[pos]
    pos += 1
    replacement_parts.append(naptr[pos:pos+label_len].decode('ascii'))
    pos += label_len
replacement = '.'.join(replacement_parts)

# 打印结果
print(f"Order: {order}")
print(f"Preference: {preference}")
print(f"Flags: {flags}")
print(f"Service: {service}")
print(f"Regexp: {regexp}")
print(f"Replacement: {replacement}")

关键说明

  • 不要尝试直接对整个rdata进行转码,因为其中包含不可见控制字符,转码后必然出现\x00、\x0c等转义序列。
  • Scapy会自动根据DNS记录类型选择对应的解析类,直接访问ans[0][1][DNS].an即可得到结构化的NAPTR记录对象,这是最简便的方式。

内容的提问来源于stack exchange,提问作者dennis_10-33

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:55:28