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

Scapy改写DNS应答字段后数据包长度异常问题求助

问题描述

拦截DNS响应并改写应答字段中的IP地址以植入代理,替换DNS数据结构中的目标IP后,发现原DNS数据包长度为401,修改后变为921。字节对比显示对应mqtt的0x04被替换为0xc0,怀疑是Scapy使用方式错误导致。

复现的字节差异:

mismatch old: 401 new: 921
dns1[0]: b'ac81818000010006000d0000046d7174740b7765'
dns2[0]: b'ac81818000010006000d0000046d7174740b7765'
dns1[20]: b'6174686572666c6f7703636f6d0000010001    c00c'
dns2[20]: b'6174686572666c6f7703636f6d0000010001    046d'
dns1[40]: b'00050001000000e4003c2177656174686572666c'
dns2[40]: b'7174740b77656174686572666c6f7703636f6d00'

复现代码:

import sys
import binascii
import scapy.all as scapy
base_dns = """
ac81818000010006000d0000046d7174740b77656174686572666c6f7703636f
6d0000010001c00c00050001000000e4003c2177656174686572666c6f772d6d
7174742d3930343536396236613839613961643503656c620975732d65617374
2d3109616d617a6f6e617773c01dc032000100010000003c0004369cffb3c032
000100010000003c0004365127ddc032000100010000003c00042cd9c48ec032
000100010000003c0004035c8c32c032000100010000003c000422ee66660000
02000100045d29001401620c726f6f742d73657276657273036e657400000002
000100045d290004016bc0cb000002000100045d2900040166c0cb0000020001
00045d2900040163c0cb000002000100045d2900040164c0cb00000200010004
5d290004016cc0cb000002000100045d2900040165c0cb000002000100045d29
0004016ac0cb000002000100045d2900040169c0cb000002000100045d290004
016dc0cb000002000100045d2900040161c0cb000002000100045d2900040168
c0cb000002000100045d2900040167c0cb
"""

if __name__ == "__main__":
    dns_l = base_dns.split('\n')
    new_dns = ''.join(dns_l)
    dns_b = binascii.a2b_hex(new_dns)
    dns = scapy.DNS(dns_b)
    b_dns_1 = bytes(dns)
    dns_len_1 = len(b_dns_1)
    #print(dns.show(dump=True))
    dns.an[1].rdata = '10.135.0.1'
    b_dns_2 = bytes(dns)
    dns_len_2 = len(b_dns_2)
    #print(dns.show(dump=True))
    if dns_len_1 != dns_len_2:
        print('mismatch old: ' + str(dns_len_1) + ' new: ' + str(dns_len_2))
        for i in range(0, min(dns_len_1, dns_len_2), 20):
            print('dns1[' + str(i) + ']:', binascii.b2a_hex(b_dns_1[i:i+20]))
            print('dns2[' + str(i) + ']:', binascii.b2a_hex(b_dns_2[i:i+20]))
        sys.exit(1)
    sys.exit(0)
问题分析
  1. DNS压缩指针未被保留:原DNS响应使用了大量域名压缩指针(如c00c、c032等)来减少数据包大小,Scapy默认在修改DNS数据包后生成字节流时,不会自动重新应用DNS压缩,导致所有压缩指针被展开为完整域名,直接造成数据包长度暴增。
  2. rdata赋值类型错误:若误修改CNAME类型记录(type=5),直接赋值IP字符串会被Scapy误解析为域名,将IP以域名标签格式写入数据包,而非保持指针或正确的记录格式,进一步破坏数据包结构。
解决方案

方案1:启用Scapy的DNS压缩功能

在将修改后的DNS对象转换为字节流时,指定启用压缩,让Scapy重新对域名进行压缩,恢复原有的指针结构:

b_dns_2 = bytes(dns, compression=True)

方案2:确保rdata赋值为正确的二进制格式

对于A类型记录(type=1),直接赋值二进制IP而非字符串,避免Scapy误解析,保证写入的是标准A记录所需的4字节IP数据:

# 将IP转换为4字节二进制格式
dns.an[1].rdata = scapy.IP('10.135.0.1').pack()

方案3:确认修改的是正确的DNS记录

先检查dns.an数组中的记录类型,确保修改的是A类型记录(type=1)而非CNAME或其他类型,避免误操作:

# 打印所有应答记录的类型,确认目标记录
for idx, record in enumerate(dns.an):
    print(f"Record {idx}: type={record.type}, rdata={record.rdata}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:22:02