当前位置:   article > 正文

DPKT - python修改数据包_python 修改pcap端口号

python 修改pcap端口号

20200914 -

0. 引言

翻出来很久之前的代码, 当时是测试是否可以修改PCAP包中的端口号,通过DPKT直接修改就好,例如下面的代码就是将PCAP中的一条流的端口22编程5022。

#修改端口
if tcp.dport == 22:
    tcp.dport = 5022
if tcp.sport == 22:
    tcp.sport = 5022
  • 1
  • 2
  • 3
  • 4
  • 5

其实经过了这个步骤,如果你不需要校验和必须正确的话,在wireshark中是可以解析的(不开TCP校验和)。本篇文章中,记录一下怎么修改TCP内容后,同时保证校验和正确。

1. 校验和计算

IP头部中的校验和,只是校验了IP头部,并不对数据进行校验;但TCP/UDP是校验的头部加数据。校验和的公式都是一样的,都是加起来最后取反码,具体可以参考文章[1]。在TCP/UDP的计算过程中,需要加一个伪头部,然后如果整体数据是奇数的话,还需要最后补0。

2. DPKT的代码

直接上代码。

#! /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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

经过测试,这部分代码在python2和python3都能测试成功,dpkt版本1.9.3;测试的方法就是下载了转换后的数据包,利用wireshark查看(其实代码中已经查看assert部分)。

参考

[1]校验和计算方法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/200890
推荐阅读
相关标签
  

闽ICP备14008679号