赞
踩
20200914 -
翻出来很久之前的代码, 当时是测试是否可以修改PCAP包中的端口号,通过DPKT直接修改就好,例如下面的代码就是将PCAP中的一条流的端口22编程5022。
#修改端口
if tcp.dport == 22:
tcp.dport = 5022
if tcp.sport == 22:
tcp.sport = 5022
其实经过了这个步骤,如果你不需要校验和必须正确的话,在wireshark中是可以解析的(不开TCP校验和)。本篇文章中,记录一下怎么修改TCP内容后,同时保证校验和正确。
IP头部中的校验和,只是校验了IP头部,并不对数据进行校验;但TCP/UDP是校验的头部加数据。校验和的公式都是一样的,都是加起来最后取反码,具体可以参考文章[1]。在TCP/UDP的计算过程中,需要加一个伪头部,然后如果整体数据是奇数的话,还需要最后补0。
直接上代码。
#! /usr/bin/python3 #coding:utf-8 #Auther:VChao #2020/09/14 import 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.data tcp = ip.data #修改端口 if tcp.dport == 22: tcp.dport = 5022 if 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()) == 0 ip.data = tcp temp = 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]校验和计算方法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。