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)
问题分析
- DNS压缩指针未被保留:原DNS响应使用了大量域名压缩指针(如
c00c、c032等)来减少数据包大小,Scapy默认在修改DNS数据包后生成字节流时,不会自动重新应用DNS压缩,导致所有压缩指针被展开为完整域名,直接造成数据包长度暴增。 - 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
相关产品推荐
相关产品推荐

