本文主要是介绍DPKT - python修改数据包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
20200914 -
0. 引言
翻出来很久之前的代码, 当时是测试是否可以修改PCAP包中的端口号,通过DPKT直接修改就好,例如下面的代码就是将PCAP中的一条流的端口22编程5022。
#修改端口
if tcp.dport == 22:tcp.dport = 5022
if tcp.sport == 22:tcp.sport = 5022
其实经过了这个步骤,如果你不需要校验和必须正确的话,在wireshark中是可以解析的(不开TCP校验和)。本篇文章中,记录一下怎么修改TCP内容后,同时保证校验和正确。
1. 校验和计算
IP头部中的校验和,只是校验了IP头部,并不对数据进行校验;但TCP/UDP是校验的头部加数据。校验和的公式都是一样的,都是加起来最后取反码,具体可以参考文章[1]。在TCP/UDP的计算过程中,需要加一个伪头部,然后如果整体数据是奇数的话,还需要最后补0。
2. DPKT的代码
直接上代码。
#! /usr/bin/python3
#coding:utf-8
#Auther:VChao
#2020/09/14import dpkt
import struct def main():with open("ssh.pcap","rb") as fin:with open("res.pcap","wb") as fout:pcapin = dpkt.pcap.Reader(fin)pcapout = dpkt.pcap.Writer(fout)for ts,buf in pcapin:Eth = dpkt.ethernet.Ethernet(buf)ip = Eth.datatcp = ip.data#修改端口if tcp.dport == 22:tcp.dport = 5022if tcp.sport == 22:tcp.sport = 5022#计算伪头部 - UDP/TCP都必须增加伪头部,#其中'\x00\x06'是TCP协议号,UDP为0x17#伪头部结构# 0 ------ 15 ------ 31# | 32位源IP | # | 32位目的IP |# |0 |8位协议 |16位TCP长度|# -------------------------pseheader = ip.src + ip.dst + b'\x00' * 2 + b'\x00\x06' + struct.pack('>I', len(tcp))#将原始TCP的校验和置零 tcp.sum = 0#拿到所有的tcp数据all_tcp = tcp.pack()#如果TCP数据是奇数,要补零,但是测试中发现不加也没事,可能是底层库帮忙做了if len(all_tcp) % 2 != 0: all_tcp += b'\x00'tcp.sum = dpkt.in_cksum(pseheader + all_tcp)#验证校验和是否正确assert dpkt.in_cksum(pseheader + tcp.pack()) == 0ip.data = tcptemp = dpkt.ethernet.Ethernet(src = Eth.src, dst = Eth.dst, type= Eth.type, data = ip)pcapout.writepkt(temp, ts = ts)if __name__ == "__main__":main()
经过测试,这部分代码在python2和python3都能测试成功,dpkt版本1.9.3
;测试的方法就是下载了转换后的数据包,利用wireshark查看(其实代码中已经查看assert部分)。
参考
[1]校验和计算方法
这篇关于DPKT - python修改数据包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!